aboutsummaryrefslogtreecommitdiff
path: root/src/lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/serde/de.rs436
-rw-r--r--src/lua/serde/error.rs58
-rw-r--r--src/lua/serde/mod.rs57
-rw-r--r--src/lua/serde/ser.rs481
4 files changed, 1032 insertions, 0 deletions
diff --git a/src/lua/serde/de.rs b/src/lua/serde/de.rs
new file mode 100644
index 0000000..4d78a83
--- /dev/null
+++ b/src/lua/serde/de.rs
@@ -0,0 +1,436 @@
+// vendored from https://github.com/zrkn/rlua_serde because it dependend on an outdated rlua version
+// Copyright (c) 2018 zrkn <zrkn@email.su>, licensed under the MIT License
+
+use serde::de::IntoDeserializer;
+use serde::{self, forward_to_deserialize_any};
+
+use rlua::{TablePairs, TableSequence, Value};
+
+use super::error::{Error, Result};
+
+pub struct Deserializer<'lua> {
+ pub value: Value<'lua>,
+}
+
+impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
+ type Error = Error;
+
+ #[inline]
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ Value::Nil => visitor.visit_unit(),
+ Value::Boolean(v) => visitor.visit_bool(v),
+ Value::Integer(v) => visitor.visit_i64(v),
+ Value::Number(v) => visitor.visit_f64(v),
+ Value::String(v) => visitor.visit_str(v.to_str()?),
+ Value::Table(v) => {
+ let len = v.len()? as usize;
+ let mut deserializer = MapDeserializer(v.pairs(), None);
+ let map = visitor.visit_map(&mut deserializer)?;
+ let remaining = deserializer.0.count();
+ if remaining == 0 {
+ Ok(map)
+ } else {
+ Err(serde::de::Error::invalid_length(
+ len,
+ &"fewer elements in array",
+ ))
+ }
+ }
+ _ => Err(serde::de::Error::custom("invalid value type")),
+ }
+ }
+
+ #[inline]
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ Value::Nil => visitor.visit_none(),
+ _ => visitor.visit_some(self),
+ }
+ }
+
+ #[inline]
+ fn deserialize_enum<V>(
+ self,
+ _name: &str,
+ _variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ let (variant, value) = match self.value {
+ Value::Table(value) => {
+ let mut iter = value.pairs::<String, Value>();
+ let (variant, value) = match iter.next() {
+ Some(v) => v?,
+ None => {
+ return Err(serde::de::Error::invalid_value(
+ serde::de::Unexpected::Map,
+ &"map with a single key",
+ ))
+ }
+ };
+
+ if iter.next().is_some() {
+ return Err(serde::de::Error::invalid_value(
+ serde::de::Unexpected::Map,
+ &"map with a single key",
+ ));
+ }
+ (variant, Some(value))
+ }
+ Value::String(variant) => (variant.to_str()?.to_owned(), None),
+ _ => return Err(serde::de::Error::custom("bad enum value")),
+ };
+
+ visitor.visit_enum(EnumDeserializer { variant, value })
+ }
+
+ #[inline]
+ fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ Value::Table(v) => {
+ let len = v.len()? as usize;
+ let mut deserializer = SeqDeserializer(v.sequence_values());
+ let seq = visitor.visit_seq(&mut deserializer)?;
+ let remaining = deserializer.0.count();
+ if remaining == 0 {
+ Ok(seq)
+ } else {
+ Err(serde::de::Error::invalid_length(
+ len,
+ &"fewer elements in array",
+ ))
+ }
+ }
+ _ => Err(serde::de::Error::custom("invalid value type")),
+ }
+ }
+
+ #[inline]
+ fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ self.deserialize_seq(visitor)
+ }
+
+ #[inline]
+ fn deserialize_tuple_struct<V>(
+ self,
+ _name: &'static str,
+ _len: usize,
+ visitor: V,
+ ) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ self.deserialize_seq(visitor)
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
+ byte_buf unit unit_struct newtype_struct
+ map struct identifier ignored_any
+ }
+}
+
+struct SeqDeserializer<'lua>(TableSequence<'lua, Value<'lua>>);
+
+impl<'lua, 'de> serde::de::SeqAccess<'de> for SeqDeserializer<'lua> {
+ type Error = Error;
+
+ fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ match self.0.next() {
+ Some(value) => seed.deserialize(Deserializer { value: value? }).map(Some),
+ None => Ok(None),
+ }
+ }
+
+ fn size_hint(&self) -> Option<usize> {
+ match self.0.size_hint() {
+ (lower, Some(upper)) if lower == upper => Some(upper),
+ _ => None,
+ }
+ }
+}
+
+struct MapDeserializer<'lua>(
+ TablePairs<'lua, Value<'lua>, Value<'lua>>,
+ Option<Value<'lua>>,
+);
+
+impl<'lua, 'de> serde::de::MapAccess<'de> for MapDeserializer<'lua> {
+ type Error = Error;
+
+ fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ match self.0.next() {
+ Some(item) => {
+ let (key, value) = item?;
+ self.1 = Some(value);
+ let key_de = Deserializer { value: key };
+ seed.deserialize(key_de).map(Some)
+ }
+ None => Ok(None),
+ }
+ }
+
+ fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ match self.1.take() {
+ Some(value) => seed.deserialize(Deserializer { value }),
+ None => Err(serde::de::Error::custom("value is missing")),
+ }
+ }
+
+ fn size_hint(&self) -> Option<usize> {
+ match self.0.size_hint() {
+ (lower, Some(upper)) if lower == upper => Some(upper),
+ _ => None,
+ }
+ }
+}
+
+struct EnumDeserializer<'lua> {
+ variant: String,
+ value: Option<Value<'lua>>,
+}
+
+impl<'lua, 'de> serde::de::EnumAccess<'de> for EnumDeserializer<'lua> {
+ type Error = Error;
+ type Variant = VariantDeserializer<'lua>;
+
+ fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant)>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ let variant = self.variant.into_deserializer();
+ let variant_access = VariantDeserializer { value: self.value };
+ seed.deserialize(variant).map(|v| (v, variant_access))
+ }
+}
+
+struct VariantDeserializer<'lua> {
+ value: Option<Value<'lua>>,
+}
+
+impl<'lua, 'de> serde::de::VariantAccess<'de> for VariantDeserializer<'lua> {
+ type Error = Error;
+
+ fn unit_variant(self) -> Result<()> {
+ match self.value {
+ Some(_) => Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::NewtypeVariant,
+ &"unit variant",
+ )),
+ None => Ok(()),
+ }
+ }
+
+ fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
+ where
+ T: serde::de::DeserializeSeed<'de>,
+ {
+ match self.value {
+ Some(value) => seed.deserialize(Deserializer { value }),
+ None => Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"newtype variant",
+ )),
+ }
+ }
+
+ fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ Some(value) => serde::Deserializer::deserialize_seq(Deserializer { value }, visitor),
+ None => Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"tuple variant",
+ )),
+ }
+ }
+
+ fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
+ where
+ V: serde::de::Visitor<'de>,
+ {
+ match self.value {
+ Some(value) => serde::Deserializer::deserialize_map(Deserializer { value }, visitor),
+ None => Err(serde::de::Error::invalid_type(
+ serde::de::Unexpected::UnitVariant,
+ &"struct variant",
+ )),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use rlua::Lua;
+
+ use super::super::from_value;
+ use serde::Deserialize;
+
+ #[test]
+ fn test_struct() {
+ #[derive(Deserialize, PartialEq, Debug)]
+ struct Test {
+ int: u32,
+ seq: Vec<String>,
+ map: std::collections::HashMap<i32, i32>,
+ empty: Vec<()>,
+ }
+
+ let expected = Test {
+ int: 1,
+ seq: vec!["a".to_owned(), "b".to_owned()],
+ map: vec![(1, 2), (4, 1)].into_iter().collect(),
+ empty: vec![],
+ };
+
+ println!("{:?}", expected);
+ let lua = Lua::new();
+ lua.context(|lua| {
+ let value = lua
+ .load(
+ r#"
+ a = {}
+ a.int = 1
+ a.seq = {"a", "b"}
+ a.map = {2, [4]=1}
+ a.empty = {}
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+ });
+ }
+
+ #[test]
+ fn test_tuple() {
+ #[derive(Deserialize, PartialEq, Debug)]
+ struct Rgb(u8, u8, u8);
+
+ let lua = Lua::new();
+ lua.context(|lua| {
+ let expected = Rgb(1, 2, 3);
+ let value = lua
+ .load(
+ r#"
+ a = {1, 2, 3}
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+
+ let expected = (1, 2, 3);
+ let value = lua
+ .load(
+ r#"
+ a = {1, 2, 3}
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+ });
+ }
+
+ #[test]
+ fn test_enum() {
+ #[derive(Deserialize, PartialEq, Debug)]
+ enum E {
+ Unit,
+ Newtype(u32),
+ Tuple(u32, u32),
+ Struct { a: u32 },
+ }
+
+ let lua = Lua::new();
+ lua.context(|lua| {
+ let expected = E::Unit;
+ let value = lua
+ .load(
+ r#"
+ return "Unit"
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+
+ let expected = E::Newtype(1);
+ let value = lua
+ .load(
+ r#"
+ a = {}
+ a["Newtype"] = 1
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+
+ let expected = E::Tuple(1, 2);
+ let value = lua
+ .load(
+ r#"
+ a = {}
+ a["Tuple"] = {1, 2}
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+
+ let expected = E::Struct { a: 1 };
+ let value = lua
+ .load(
+ r#"
+ a = {}
+ a["Struct"] = {}
+ a["Struct"]["a"] = 1
+ return a
+ "#,
+ )
+ .eval()
+ .unwrap();
+ let got = from_value(value).unwrap();
+ assert_eq!(expected, got);
+ });
+ }
+}
diff --git a/src/lua/serde/error.rs b/src/lua/serde/error.rs
new file mode 100644
index 0000000..8d5debf
--- /dev/null
+++ b/src/lua/serde/error.rs
@@ -0,0 +1,58 @@
+// vendored from https://github.com/zrkn/rlua_serde because it dependend on an outdated rlua version
+// Copyright (c) 2018 zrkn <zrkn@email.su>, licensed under the MIT License
+
+use std::error::Error as StdError;
+use std::fmt;
+use std::result::Result as StdResult;
+
+use rlua::Error as LuaError;
+use serde;
+
+#[derive(Debug)]
+pub struct Error(LuaError);
+
+pub type Result<T> = StdResult<T, Error>;
+
+impl From<LuaError> for Error {
+ fn from(err: LuaError) -> Error {
+ Error(err)
+ }
+}
+
+impl From<Error> for LuaError {
+ fn from(err: Error) -> LuaError {
+ err.0
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ self.0.fmt(fmt)
+ }
+}
+
+impl StdError for Error {
+ fn description(&self) -> &'static str {
+ "Failed to serialize to Lua value"
+ }
+}
+
+impl serde::ser::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Self {
+ Error(LuaError::ToLuaConversionError {
+ from: "serialize",
+ to: "value",
+ message: Some(format!("{}", msg)),
+ })
+ }
+}
+
+impl serde::de::Error for Error {
+ fn custom<T: fmt::Display>(msg: T) -> Self {
+ Error(LuaError::FromLuaConversionError {
+ from: "value",
+ to: "deserialize",
+ message: Some(format!("{}", msg)),
+ })
+ }
+}
diff --git a/src/lua/serde/mod.rs b/src/lua/serde/mod.rs
new file mode 100644
index 0000000..82a928a
--- /dev/null
+++ b/src/lua/serde/mod.rs
@@ -0,0 +1,57 @@
+// vendored from https://github.com/zrkn/rlua_serde because it dependend on an outdated rlua version
+// Copyright (c) 2018 zrkn <zrkn@email.su>, licensed under the MIT License
+
+//! This crate allows you to serialize and deserialize any type that implements
+//! `serde::Serialize` and `serde::Deserialize` into/from `rlua::Value`.
+//!
+//! Implementation is similar to `serde_json::Value`
+//!
+//! Example usage:
+//!
+//! ```rust
+//! extern crate serde;
+//! #[macro_use]
+//! extern crate serde_derive;
+//! extern crate rlua;
+//! extern crate rlua_serde;
+//!
+//! fn main() {
+//! #[derive(Serialize, Deserialize)]
+//! struct Foo {
+//! bar: u32,
+//! baz: Vec<String>,
+//! }
+//!
+//! let lua = rlua::Lua::new();
+//! lua.context(|lua| {
+//! let foo = Foo {
+//! bar: 42,
+//! baz: vec![String::from("fizz"), String::from("buzz")],
+//! };
+//!
+//! let value = rlua_serde::to_value(lua, &foo).unwrap();
+//! lua.globals().set("value", value).unwrap();
+//! lua.load(
+//! r#"
+//! assert(value["bar"] == 42)
+//! assert(value["baz"][2] == "buzz")
+//! "#).exec().unwrap();
+//! });
+//! }
+//! ```
+
+pub mod de;
+pub mod error;
+pub mod ser;
+
+use rlua::{Context, Error, Value};
+
+pub fn to_value<T: serde::Serialize>(lua: Context, t: T) -> Result<Value, Error> {
+ let serializer = ser::Serializer { lua };
+ Ok(t.serialize(serializer)?)
+}
+
+pub fn from_value<'de, T: serde::Deserialize<'de>>(value: Value<'de>) -> Result<T, Error> {
+ let deserializer = de::Deserializer { value };
+ Ok(T::deserialize(deserializer)?)
+}
diff --git a/src/lua/serde/ser.rs b/src/lua/serde/ser.rs
new file mode 100644
index 0000000..8af978a
--- /dev/null
+++ b/src/lua/serde/ser.rs
@@ -0,0 +1,481 @@
+// vendored from https://github.com/zrkn/rlua_serde because it dependend on an outdated rlua version
+// Copyright (c) 2018 zrkn <zrkn@email.su>, licensed under the MIT License
+
+use serde;
+
+use rlua::{Context, String as LuaString, Table, Value};
+
+use super::error::{Error, Result};
+use super::to_value;
+
+pub struct Serializer<'lua> {
+ pub lua: Context<'lua>,
+}
+
+impl<'lua> serde::Serializer for Serializer<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ type SerializeSeq = SerializeVec<'lua>;
+ type SerializeTuple = SerializeVec<'lua>;
+ type SerializeTupleStruct = SerializeVec<'lua>;
+ type SerializeTupleVariant = SerializeTupleVariant<'lua>;
+ type SerializeMap = SerializeMap<'lua>;
+ type SerializeStruct = SerializeMap<'lua>;
+ type SerializeStructVariant = SerializeStructVariant<'lua>;
+
+ #[inline]
+ fn serialize_bool(self, value: bool) -> Result<Value<'lua>> {
+ Ok(Value::Boolean(value))
+ }
+
+ #[inline]
+ fn serialize_i8(self, value: i8) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i16(self, value: i16) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i32(self, value: i32) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_i64(self, value: i64) -> Result<Value<'lua>> {
+ Ok(Value::Integer(value))
+ }
+
+ #[inline]
+ fn serialize_u8(self, value: u8) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u16(self, value: u16) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u32(self, value: u32) -> Result<Value<'lua>> {
+ self.serialize_i64(i64::from(value))
+ }
+
+ #[inline]
+ fn serialize_u64(self, value: u64) -> Result<Value<'lua>> {
+ self.serialize_i64(value as i64)
+ }
+
+ #[inline]
+ fn serialize_f32(self, value: f32) -> Result<Value<'lua>> {
+ self.serialize_f64(f64::from(value))
+ }
+
+ #[inline]
+ fn serialize_f64(self, value: f64) -> Result<Value<'lua>> {
+ Ok(Value::Number(value))
+ }
+
+ #[inline]
+ fn serialize_char(self, value: char) -> Result<Value<'lua>> {
+ let mut s = String::new();
+ s.push(value);
+ self.serialize_str(&s)
+ }
+
+ #[inline]
+ fn serialize_str(self, value: &str) -> Result<Value<'lua>> {
+ Ok(Value::String(self.lua.create_string(value)?))
+ }
+
+ #[inline]
+ fn serialize_bytes(self, value: &[u8]) -> Result<Value<'lua>> {
+ Ok(Value::Table(
+ self.lua.create_sequence_from(value.iter().cloned())?,
+ ))
+ }
+
+ #[inline]
+ fn serialize_unit(self) -> Result<Value<'lua>> {
+ Ok(Value::Nil)
+ }
+
+ #[inline]
+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Value<'lua>> {
+ self.serialize_unit()
+ }
+
+ #[inline]
+ fn serialize_unit_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Value<'lua>> {
+ self.serialize_str(variant)
+ }
+
+ #[inline]
+ fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value<'lua>>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_newtype_variant<T>(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Value<'lua>>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ let table = self.lua.create_table()?;
+ let variant = self.lua.create_string(variant)?;
+ let value = to_value(self.lua, value)?;
+ table.set(variant, value)?;
+ Ok(Value::Table(table))
+ }
+
+ #[inline]
+ fn serialize_none(self) -> Result<Value<'lua>> {
+ self.serialize_unit()
+ }
+
+ #[inline]
+ fn serialize_some<T>(self, value: &T) -> Result<Value<'lua>>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ value.serialize(self)
+ }
+
+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+ let table = self.lua.create_table()?;
+ Ok(SerializeVec {
+ lua: self.lua,
+ idx: 1,
+ table,
+ })
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ _name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleStruct> {
+ self.serialize_seq(Some(len))
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeTupleVariant> {
+ let name = self.lua.create_string(variant)?;
+ let table = self.lua.create_table()?;
+ Ok(SerializeTupleVariant {
+ lua: self.lua,
+ idx: 1,
+ name,
+ table,
+ })
+ }
+
+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+ let table = self.lua.create_table()?;
+ Ok(SerializeMap {
+ lua: self.lua,
+ next_key: None,
+ table,
+ })
+ }
+
+ fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
+ self.serialize_map(Some(len))
+ }
+
+ fn serialize_struct_variant(
+ self,
+ _name: &'static str,
+ _variant_index: u32,
+ variant: &'static str,
+ _len: usize,
+ ) -> Result<Self::SerializeStructVariant> {
+ let name = self.lua.create_string(variant)?;
+ let table = self.lua.create_table()?;
+ Ok(SerializeStructVariant {
+ lua: self.lua,
+ name,
+ table,
+ })
+ }
+}
+
+pub struct SerializeVec<'lua> {
+ lua: Context<'lua>,
+ table: Table<'lua>,
+ idx: u64,
+}
+
+impl<'lua> serde::ser::SerializeSeq for SerializeVec<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ self.table.set(self.idx, to_value(self.lua, value)?)?;
+ self.idx += 1;
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ Ok(Value::Table(self.table))
+ }
+}
+
+impl<'lua> serde::ser::SerializeTuple for SerializeVec<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_element<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+impl<'lua> serde::ser::SerializeTupleStruct for SerializeVec<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(self, value)
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ serde::ser::SerializeSeq::end(self)
+ }
+}
+
+pub struct SerializeTupleVariant<'lua> {
+ lua: Context<'lua>,
+ name: LuaString<'lua>,
+ table: Table<'lua>,
+ idx: u64,
+}
+
+impl<'lua> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ self.table.set(self.idx, to_value(self.lua, value)?)?;
+ self.idx += 1;
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ let table = self.lua.create_table()?;
+ table.set(self.name, self.table)?;
+ Ok(Value::Table(table))
+ }
+}
+
+pub struct SerializeMap<'lua> {
+ lua: Context<'lua>,
+ table: Table<'lua>,
+ next_key: Option<Value<'lua>>,
+}
+
+impl<'lua> serde::ser::SerializeMap for SerializeMap<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_key<T>(&mut self, key: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ self.next_key = Some(to_value(self.lua, key)?);
+ Ok(())
+ }
+
+ fn serialize_value<T>(&mut self, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ let key = self.next_key.take();
+ // Panic because this indicates a bug in the program rather than an
+ // expected failure.
+ let key = key.expect("serialize_value called before serialize_key");
+ self.table.set(key, to_value(self.lua, value)?)?;
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ Ok(Value::Table(self.table))
+ }
+}
+
+impl<'lua> serde::ser::SerializeStruct for SerializeMap<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ serde::ser::SerializeMap::serialize_key(self, key)?;
+ serde::ser::SerializeMap::serialize_value(self, value)
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ serde::ser::SerializeMap::end(self)
+ }
+}
+
+pub struct SerializeStructVariant<'lua> {
+ lua: Context<'lua>,
+ name: LuaString<'lua>,
+ table: Table<'lua>,
+}
+
+impl<'lua> serde::ser::SerializeStructVariant for SerializeStructVariant<'lua> {
+ type Ok = Value<'lua>;
+ type Error = Error;
+
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
+ where
+ T: ?Sized + serde::Serialize,
+ {
+ self.table.set(key, to_value(self.lua, value)?)?;
+ Ok(())
+ }
+
+ fn end(self) -> Result<Value<'lua>> {
+ let table = self.lua.create_table()?;
+ table.set(self.name, self.table)?;
+ Ok(Value::Table(table))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use rlua::Lua;
+ use serde::Serialize;
+
+ #[test]
+ fn test_struct() {
+ #[derive(Serialize)]
+ struct Test {
+ int: u32,
+ seq: Vec<&'static str>,
+ }
+
+ let test = Test {
+ int: 1,
+ seq: vec!["a", "b"],
+ };
+
+ let lua = Lua::new();
+ lua.context(|lua| {
+ let value = to_value(lua, &test).unwrap();
+ lua.globals().set("value", value).unwrap();
+ lua.load(
+ r#"
+ assert(value["int"] == 1)
+ assert(value["seq"][1] == "a")
+ assert(value["seq"][2] == "b")
+ "#,
+ )
+ .exec()
+ })
+ .unwrap()
+ }
+
+ #[test]
+ fn test_num() {
+ #[derive(Serialize)]
+ enum E {
+ Unit,
+ Newtype(u32),
+ Tuple(u32, u32),
+ Struct { a: u32 },
+ }
+
+ let lua = Lua::new();
+
+ lua.context(|lua| {
+ let u = E::Unit;
+ let value = to_value(lua, &u).unwrap();
+ lua.globals().set("value", value).unwrap();
+ lua.load(
+ r#"
+ assert(value == "Unit")
+ "#,
+ )
+ .exec()
+ .unwrap();
+
+ let n = E::Newtype(1);
+ let value = to_value(lua, &n).unwrap();
+ lua.globals().set("value", value).unwrap();
+ lua.load(
+ r#"
+ assert(value["Newtype"] == 1)
+ "#,
+ )
+ .exec()
+ .unwrap();
+
+ let t = E::Tuple(1, 2);
+ let value = to_value(lua, &t).unwrap();
+ lua.globals().set("value", value).unwrap();
+ lua.load(
+ r#"
+ assert(value["Tuple"][1] == 1)
+ assert(value["Tuple"][2] == 2)
+ "#,
+ )
+ .exec()
+ .unwrap();
+
+ let s = E::Struct { a: 1 };
+ let value = to_value(lua, &s).unwrap();
+ lua.globals().set("value", value).unwrap();
+ lua.load(
+ r#"
+ assert(value["Struct"]["a"] == 1)
+ "#,
+ )
+ .exec()
+ })
+ .unwrap();
+ }
+}