fully adapt to mlua
This commit is contained in:
parent
9d12a4fc4b
commit
964efbbc73
18
README.md
18
README.md
|
@ -1,22 +1,22 @@
|
||||||
# rlue_serde
|
# rlue_serde
|
||||||
|
|
||||||
Implementation of [serde](https://serde.rs/) Serializer/Deserializer for [rlua::Value](https://docs.rs/rlua/0.12/rlua/enum.Value.html)
|
Implementation of [serde](https://serde.rs/) Serializer/Deserializer for [mlua::Value](https://docs.rs/mlua/0.12/mlua/enum.Value.html)
|
||||||
|
|
||||||
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
|
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
|
||||||
[![Crates.io](https://img.shields.io/crates/v/rlua_serde.svg)](https://crates.io/crates/rlua_serde)
|
[![Crates.io](https://img.shields.io/crates/v/mlua_serde.svg)](https://crates.io/crates/mlua_serde)
|
||||||
[![Documentation](https://docs.rs/rlua_serde/badge.svg)][dox]
|
[![Documentation](https://docs.rs/mlua_serde/badge.svg)][dox]
|
||||||
|
|
||||||
More information about this crate can be found in the [crate documentation][dox].
|
More information about this crate can be found in the [crate documentation][dox].
|
||||||
|
|
||||||
[dox]: https://docs.rs/rlua_serde/*/rlua_serde/
|
[dox]: https://docs.rs/mlua_serde/*/mlua_serde/
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To use `rlua_serde`, first add this to your `Cargo.toml`:
|
To use `mlua_serde`, first add this to your `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rlua_serde = "0.4"
|
mlua_serde = "0.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, you can use `to_value`/`from_value` functions to serialize/deserialize:
|
Next, you can use `to_value`/`from_value` functions to serialize/deserialize:
|
||||||
|
@ -29,20 +29,18 @@ struct Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let lua = rlua::Lua::new();
|
let lua = mlua::Lua::new();
|
||||||
lua.context(|lua| {
|
|
||||||
let foo = Foo {
|
let foo = Foo {
|
||||||
bar: 42,
|
bar: 42,
|
||||||
baz: vec![String::from("fizz"), String::from("buzz")],
|
baz: vec![String::from("fizz"), String::from("buzz")],
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = rlua_serde::to_value(lua, &foo).unwrap();
|
let value = mlua_serde::to_value(lua, &foo).unwrap();
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(
|
lua.load(
|
||||||
r#"
|
r#"
|
||||||
assert(value["bar"] == 42)
|
assert(value["bar"] == 42)
|
||||||
assert(value["baz"][2] == "buzz")
|
assert(value["baz"][2] == "buzz")
|
||||||
"#).exec().unwrap();
|
"#).exec().unwrap();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,6 +3,6 @@ let
|
||||||
in
|
in
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
rustc cargo rls lua5_3 pkg-config
|
rustc cargo rls lua5_3 pkg-config rustfmt
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
173
src/de.rs
173
src/de.rs
|
@ -1,11 +1,10 @@
|
||||||
use serde;
|
use serde;
|
||||||
use serde::de::IntoDeserializer;
|
use serde::de::IntoDeserializer;
|
||||||
|
|
||||||
use mlua::{Value, TablePairs, TableSequence};
|
use mlua::{TablePairs, TableSequence, Value};
|
||||||
|
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
|
|
||||||
|
|
||||||
pub struct Deserializer<'lua> {
|
pub struct Deserializer<'lua> {
|
||||||
pub value: Value<'lua>,
|
pub value: Value<'lua>,
|
||||||
}
|
}
|
||||||
|
@ -15,7 +14,8 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Value::Nil => visitor.visit_unit(),
|
Value::Nil => visitor.visit_unit(),
|
||||||
|
@ -31,16 +31,20 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(map)
|
Ok(map)
|
||||||
} else {
|
} else {
|
||||||
Err(serde::de::Error::invalid_length(len, &"fewer elements in array"))
|
Err(serde::de::Error::invalid_length(
|
||||||
|
len,
|
||||||
|
&"fewer elements in array",
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => Err(serde::de::Error::custom("invalid value type")),
|
_ => Err(serde::de::Error::custom("invalid value type")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Value::Nil => visitor.visit_none(),
|
Value::Nil => visitor.visit_none(),
|
||||||
|
@ -50,26 +54,32 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_enum<V>(
|
fn deserialize_enum<V>(
|
||||||
self, _name: &str, _variants: &'static [&'static str], visitor: V
|
self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
) -> Result<V::Value>
|
) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
let (variant, value) = match self.value {
|
let (variant, value) = match self.value {
|
||||||
Value::Table(value) => {
|
Value::Table(value) => {
|
||||||
let mut iter = value.pairs::<String, Value>();
|
let mut iter = value.pairs::<String, Value>();
|
||||||
let (variant, value) = match iter.next() {
|
let (variant, value) = match iter.next() {
|
||||||
Some(v) => v?,
|
Some(v) => v?,
|
||||||
None => return Err(serde::de::Error::invalid_value(
|
None => {
|
||||||
|
return Err(serde::de::Error::invalid_value(
|
||||||
serde::de::Unexpected::Map,
|
serde::de::Unexpected::Map,
|
||||||
&"map with a single key",
|
&"map with a single key",
|
||||||
)),
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if iter.next().is_some() {
|
if iter.next().is_some() {
|
||||||
return Err(serde::de::Error::invalid_value(
|
return Err(serde::de::Error::invalid_value(
|
||||||
serde::de::Unexpected::Map,
|
serde::de::Unexpected::Map,
|
||||||
&"map with a single key",
|
&"map with a single key",
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
(variant, Some(value))
|
(variant, Some(value))
|
||||||
}
|
}
|
||||||
|
@ -82,7 +92,8 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Value::Table(v) => {
|
Value::Table(v) => {
|
||||||
|
@ -93,7 +104,10 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(seq)
|
Ok(seq)
|
||||||
} else {
|
} else {
|
||||||
Err(serde::de::Error::invalid_length(len, &"fewer elements in array"))
|
Err(serde::de::Error::invalid_length(
|
||||||
|
len,
|
||||||
|
&"fewer elements in array",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(serde::de::Error::custom("invalid value type")),
|
_ => Err(serde::de::Error::custom("invalid value type")),
|
||||||
|
@ -102,14 +116,21 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.deserialize_seq(visitor)
|
self.deserialize_seq(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, visitor: V) -> Result<V::Value>
|
fn deserialize_tuple_struct<V>(
|
||||||
where V: serde::de::Visitor<'de>
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value>
|
||||||
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.deserialize_seq(visitor)
|
self.deserialize_seq(visitor)
|
||||||
}
|
}
|
||||||
|
@ -121,19 +142,18 @@ impl<'lua, 'de> serde::Deserializer<'de> for Deserializer<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct SeqDeserializer<'lua>(TableSequence<'lua, Value<'lua>>);
|
struct SeqDeserializer<'lua>(TableSequence<'lua, Value<'lua>>);
|
||||||
|
|
||||||
impl<'lua, 'de> serde::de::SeqAccess<'de> for SeqDeserializer<'lua> {
|
impl<'lua, 'de> serde::de::SeqAccess<'de> for SeqDeserializer<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||||
where T: serde::de::DeserializeSeed<'de>
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.0.next() {
|
match self.0.next() {
|
||||||
Some(value) => seed.deserialize(Deserializer { value: value? })
|
Some(value) => seed.deserialize(Deserializer { value: value? }).map(Some),
|
||||||
.map(Some),
|
None => Ok(None),
|
||||||
None => Ok(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,17 +165,17 @@ impl<'lua, 'de> serde::de::SeqAccess<'de> for SeqDeserializer<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct MapDeserializer<'lua>(
|
struct MapDeserializer<'lua>(
|
||||||
TablePairs<'lua, Value<'lua>, Value<'lua>>,
|
TablePairs<'lua, Value<'lua>, Value<'lua>>,
|
||||||
Option<Value<'lua>>
|
Option<Value<'lua>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'lua, 'de> serde::de::MapAccess<'de> for MapDeserializer<'lua> {
|
impl<'lua, 'de> serde::de::MapAccess<'de> for MapDeserializer<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||||
where T: serde::de::DeserializeSeed<'de>
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.0.next() {
|
match self.0.next() {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
|
@ -163,13 +183,14 @@ impl<'lua, 'de> serde::de::MapAccess<'de> for MapDeserializer<'lua> {
|
||||||
self.1 = Some(value);
|
self.1 = Some(value);
|
||||||
let key_de = Deserializer { value: key };
|
let key_de = Deserializer { value: key };
|
||||||
seed.deserialize(key_de).map(Some)
|
seed.deserialize(key_de).map(Some)
|
||||||
},
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
|
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
|
||||||
where T: serde::de::DeserializeSeed<'de>
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.1.take() {
|
match self.1.take() {
|
||||||
Some(value) => seed.deserialize(Deserializer { value }),
|
Some(value) => seed.deserialize(Deserializer { value }),
|
||||||
|
@ -185,7 +206,6 @@ impl<'lua, 'de> serde::de::MapAccess<'de> for MapDeserializer<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct EnumDeserializer<'lua> {
|
struct EnumDeserializer<'lua> {
|
||||||
variant: String,
|
variant: String,
|
||||||
value: Option<Value<'lua>>,
|
value: Option<Value<'lua>>,
|
||||||
|
@ -196,7 +216,8 @@ impl<'lua, 'de> serde::de::EnumAccess<'de> for EnumDeserializer<'lua> {
|
||||||
type Variant = VariantDeserializer<'lua>;
|
type Variant = VariantDeserializer<'lua>;
|
||||||
|
|
||||||
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant)>
|
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant)>
|
||||||
where T: serde::de::DeserializeSeed<'de>
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
let variant = self.variant.into_deserializer();
|
let variant = self.variant.into_deserializer();
|
||||||
let variant_access = VariantDeserializer { value: self.value };
|
let variant_access = VariantDeserializer { value: self.value };
|
||||||
|
@ -204,7 +225,6 @@ impl<'lua, 'de> serde::de::EnumAccess<'de> for EnumDeserializer<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct VariantDeserializer<'lua> {
|
struct VariantDeserializer<'lua> {
|
||||||
value: Option<Value<'lua>>,
|
value: Option<Value<'lua>>,
|
||||||
}
|
}
|
||||||
|
@ -218,49 +238,46 @@ impl<'lua, 'de> serde::de::VariantAccess<'de> for VariantDeserializer<'lua> {
|
||||||
serde::de::Unexpected::NewtypeVariant,
|
serde::de::Unexpected::NewtypeVariant,
|
||||||
&"unit variant",
|
&"unit variant",
|
||||||
)),
|
)),
|
||||||
None => Ok(())
|
None => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
||||||
where T: serde::de::DeserializeSeed<'de>
|
where
|
||||||
|
T: serde::de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Some(value) => seed.deserialize(Deserializer { value }),
|
Some(value) => seed.deserialize(Deserializer { value }),
|
||||||
None => Err(serde::de::Error::invalid_type(
|
None => Err(serde::de::Error::invalid_type(
|
||||||
serde::de::Unexpected::UnitVariant,
|
serde::de::Unexpected::UnitVariant,
|
||||||
&"newtype variant",
|
&"newtype variant",
|
||||||
))
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||||
where V: serde::de::Visitor<'de>
|
where
|
||||||
|
V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Some(value) => serde::Deserializer::deserialize_seq(
|
Some(value) => serde::Deserializer::deserialize_seq(Deserializer { value }, visitor),
|
||||||
Deserializer { value }, visitor
|
|
||||||
),
|
|
||||||
None => Err(serde::de::Error::invalid_type(
|
None => Err(serde::de::Error::invalid_type(
|
||||||
serde::de::Unexpected::UnitVariant,
|
serde::de::Unexpected::UnitVariant,
|
||||||
&"tuple variant",
|
&"tuple variant",
|
||||||
))
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_variant<V>(
|
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||||
self, _fields: &'static [&'static str], visitor: V
|
where
|
||||||
) -> Result<V::Value>
|
V: serde::de::Visitor<'de>,
|
||||||
where V: serde::de::Visitor<'de>
|
|
||||||
{
|
{
|
||||||
match self.value {
|
match self.value {
|
||||||
Some(value) => serde::Deserializer::deserialize_map(
|
Some(value) => serde::Deserializer::deserialize_map(Deserializer { value }, visitor),
|
||||||
Deserializer { value }, visitor
|
|
||||||
),
|
|
||||||
None => Err(serde::de::Error::invalid_type(
|
None => Err(serde::de::Error::invalid_type(
|
||||||
serde::de::Unexpected::UnitVariant,
|
serde::de::Unexpected::UnitVariant,
|
||||||
&"struct variant",
|
&"struct variant",
|
||||||
))
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,23 +302,26 @@ mod tests {
|
||||||
int: 1,
|
int: 1,
|
||||||
seq: vec!["a".to_owned(), "b".to_owned()],
|
seq: vec!["a".to_owned(), "b".to_owned()],
|
||||||
map: vec![(1, 2), (4, 1)].into_iter().collect(),
|
map: vec![(1, 2), (4, 1)].into_iter().collect(),
|
||||||
empty: vec![]
|
empty: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("{:?}", expected);
|
println!("{:?}", expected);
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
lua.context(|lua| {
|
let value = lua
|
||||||
let value = lua.load(r#"
|
.load(
|
||||||
|
r#"
|
||||||
a = {}
|
a = {}
|
||||||
a.int = 1
|
a.int = 1
|
||||||
a.seq = {"a", "b"}
|
a.seq = {"a", "b"}
|
||||||
a.map = {2, [4]=1}
|
a.map = {2, [4]=1}
|
||||||
a.empty = {}
|
a.empty = {}
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -310,25 +330,31 @@ mod tests {
|
||||||
struct Rgb(u8, u8, u8);
|
struct Rgb(u8, u8, u8);
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
lua.context(|lua| {
|
|
||||||
let expected = Rgb(1, 2, 3);
|
let expected = Rgb(1, 2, 3);
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
a = {1, 2, 3}
|
a = {1, 2, 3}
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
|
|
||||||
let expected = (1, 2, 3);
|
let expected = (1, 2, 3);
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
a = {1, 2, 3}
|
a = {1, 2, 3}
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -342,46 +368,59 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
lua.context(|lua| {
|
|
||||||
let expected = E::Unit;
|
let expected = E::Unit;
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
return "Unit"
|
return "Unit"
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
|
|
||||||
|
|
||||||
let expected = E::Newtype(1);
|
let expected = E::Newtype(1);
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
a = {}
|
a = {}
|
||||||
a["Newtype"] = 1
|
a["Newtype"] = 1
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
|
|
||||||
let expected = E::Tuple(1, 2);
|
let expected = E::Tuple(1, 2);
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
a = {}
|
a = {}
|
||||||
a["Tuple"] = {1, 2}
|
a["Tuple"] = {1, 2}
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
|
|
||||||
let expected = E::Struct { a: 1 };
|
let expected = E::Struct { a: 1 };
|
||||||
let value = lua.load(
|
let value = lua
|
||||||
|
.load(
|
||||||
r#"
|
r#"
|
||||||
a = {}
|
a = {}
|
||||||
a["Struct"] = {}
|
a["Struct"] = {}
|
||||||
a["Struct"]["a"] = 1
|
a["Struct"]["a"] = 1
|
||||||
return a
|
return a
|
||||||
"#).eval().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.eval()
|
||||||
|
.unwrap();
|
||||||
let got = from_value(value).unwrap();
|
let got = from_value(value).unwrap();
|
||||||
assert_eq!(expected, got);
|
assert_eq!(expected, got);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,18 @@
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! let lua = mlua::Lua::new();
|
//! let lua = mlua::Lua::new();
|
||||||
//! lua.context(|lua| {
|
|
||||||
//! let foo = Foo {
|
//! let foo = Foo {
|
||||||
//! bar: 42,
|
//! bar: 42,
|
||||||
//! baz: vec![String::from("fizz"), String::from("buzz")],
|
//! baz: vec![String::from("fizz"), String::from("buzz")],
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! let value = mlua_serde::to_value(lua, &foo).unwrap();
|
//! let value = mlua_serde::to_value(&lua, &foo).unwrap();
|
||||||
//! lua.globals().set("value", value).unwrap();
|
//! lua.globals().set("value", value).unwrap();
|
||||||
//! lua.load(
|
//! lua.load(
|
||||||
//! r#"
|
//! r#"
|
||||||
//! assert(value["bar"] == 42)
|
//! assert(value["bar"] == 42)
|
||||||
//! assert(value["baz"][2] == "buzz")
|
//! assert(value["baz"][2] == "buzz")
|
||||||
//! "#).exec().unwrap();
|
//! "#).exec().unwrap();
|
||||||
//! });
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
148
src/ser.rs
148
src/ser.rs
|
@ -1,10 +1,9 @@
|
||||||
use serde;
|
use serde;
|
||||||
|
|
||||||
use mlua::{Lua, Value, Table, String as LuaString};
|
use mlua::{Lua, String as LuaString, Table, Value};
|
||||||
|
|
||||||
use to_value;
|
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
|
use to_value;
|
||||||
|
|
||||||
pub struct Serializer<'lua> {
|
pub struct Serializer<'lua> {
|
||||||
pub lua: &'lua Lua,
|
pub lua: &'lua Lua,
|
||||||
|
@ -91,7 +90,9 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize_bytes(self, value: &[u8]) -> Result<Value<'lua>> {
|
fn serialize_bytes(self, value: &[u8]) -> Result<Value<'lua>> {
|
||||||
Ok(Value::Table(self.lua.create_sequence_from(value.iter().cloned())?))
|
Ok(Value::Table(
|
||||||
|
self.lua.create_sequence_from(value.iter().cloned())?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -106,25 +107,31 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize_unit_variant(
|
fn serialize_unit_variant(
|
||||||
self, _name: &'static str, _variant_index: u32, variant: &'static str
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_variant_index: u32,
|
||||||
|
variant: &'static str,
|
||||||
) -> Result<Value<'lua>> {
|
) -> Result<Value<'lua>> {
|
||||||
self.serialize_str(variant)
|
self.serialize_str(variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize_newtype_struct<T>(
|
fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value<'lua>>
|
||||||
self, _name: &'static str, value: &T
|
where
|
||||||
) -> Result<Value<'lua>>
|
T: ?Sized + serde::Serialize,
|
||||||
where T: ?Sized + serde::Serialize,
|
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T>(
|
fn serialize_newtype_variant<T>(
|
||||||
self, _name: &'static str, _variant_index: u32,
|
self,
|
||||||
variant: &'static str, value: &T,
|
_name: &'static str,
|
||||||
|
_variant_index: u32,
|
||||||
|
variant: &'static str,
|
||||||
|
value: &T,
|
||||||
) -> Result<Value<'lua>>
|
) -> Result<Value<'lua>>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
let table = self.lua.create_table()?;
|
let table = self.lua.create_table()?;
|
||||||
let variant = self.lua.create_string(variant)?;
|
let variant = self.lua.create_string(variant)?;
|
||||||
|
@ -140,7 +147,8 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize_some<T>(self, value: &T) -> Result<Value<'lua>>
|
fn serialize_some<T>(self, value: &T) -> Result<Value<'lua>>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
@ -159,14 +167,19 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
fn serialize_tuple_struct(
|
||||||
self, _name: &'static str, len: usize,
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleStruct> {
|
) -> Result<Self::SerializeTupleStruct> {
|
||||||
self.serialize_seq(Some(len))
|
self.serialize_seq(Some(len))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
fn serialize_tuple_variant(
|
||||||
self, _name: &'static str, _variant_index: u32,
|
self,
|
||||||
variant: &'static str, _len: usize,
|
_name: &'static str,
|
||||||
|
_variant_index: u32,
|
||||||
|
variant: &'static str,
|
||||||
|
_len: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant> {
|
) -> Result<Self::SerializeTupleVariant> {
|
||||||
let name = self.lua.create_string(variant)?;
|
let name = self.lua.create_string(variant)?;
|
||||||
let table = self.lua.create_table()?;
|
let table = self.lua.create_table()?;
|
||||||
|
@ -174,7 +187,7 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
lua: self.lua,
|
lua: self.lua,
|
||||||
idx: 1,
|
idx: 1,
|
||||||
name,
|
name,
|
||||||
table
|
table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,8 +205,11 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
fn serialize_struct_variant(
|
||||||
self, _name: &'static str, _variant_index: u32,
|
self,
|
||||||
variant: &'static str, _len: usize,
|
_name: &'static str,
|
||||||
|
_variant_index: u32,
|
||||||
|
variant: &'static str,
|
||||||
|
_len: usize,
|
||||||
) -> Result<Self::SerializeStructVariant> {
|
) -> Result<Self::SerializeStructVariant> {
|
||||||
let name = self.lua.create_string(variant)?;
|
let name = self.lua.create_string(variant)?;
|
||||||
let table = self.lua.create_table()?;
|
let table = self.lua.create_table()?;
|
||||||
|
@ -203,10 +219,8 @@ impl<'lua> serde::Serializer for Serializer<'lua> {
|
||||||
table,
|
table,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct SerializeVec<'lua> {
|
pub struct SerializeVec<'lua> {
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
table: Table<'lua>,
|
table: Table<'lua>,
|
||||||
|
@ -218,7 +232,8 @@ impl<'lua> serde::ser::SerializeSeq for SerializeVec<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
self.table.set(self.idx, to_value(self.lua, value)?)?;
|
self.table.set(self.idx, to_value(self.lua, value)?)?;
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
|
@ -235,7 +250,8 @@ impl<'lua> serde::ser::SerializeTuple for SerializeVec<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
fn serialize_element<T>(&mut self, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
serde::ser::SerializeSeq::serialize_element(self, value)
|
serde::ser::SerializeSeq::serialize_element(self, value)
|
||||||
}
|
}
|
||||||
|
@ -250,7 +266,8 @@ impl<'lua> serde::ser::SerializeTupleStruct for SerializeVec<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
serde::ser::SerializeSeq::serialize_element(self, value)
|
serde::ser::SerializeSeq::serialize_element(self, value)
|
||||||
}
|
}
|
||||||
|
@ -260,7 +277,6 @@ impl<'lua> serde::ser::SerializeTupleStruct for SerializeVec<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct SerializeTupleVariant<'lua> {
|
pub struct SerializeTupleVariant<'lua> {
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
name: LuaString<'lua>,
|
name: LuaString<'lua>,
|
||||||
|
@ -273,7 +289,8 @@ impl<'lua> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
fn serialize_field<T>(&mut self, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
self.table.set(self.idx, to_value(self.lua, value)?)?;
|
self.table.set(self.idx, to_value(self.lua, value)?)?;
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
|
@ -287,11 +304,10 @@ impl<'lua> serde::ser::SerializeTupleVariant for SerializeTupleVariant<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct SerializeMap<'lua> {
|
pub struct SerializeMap<'lua> {
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
table: Table<'lua>,
|
table: Table<'lua>,
|
||||||
next_key: Option<Value<'lua>>
|
next_key: Option<Value<'lua>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> serde::ser::SerializeMap for SerializeMap<'lua> {
|
impl<'lua> serde::ser::SerializeMap for SerializeMap<'lua> {
|
||||||
|
@ -299,14 +315,16 @@ impl<'lua> serde::ser::SerializeMap for SerializeMap<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
|
fn serialize_key<T>(&mut self, key: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
self.next_key = Some(to_value(self.lua, key)?);
|
self.next_key = Some(to_value(self.lua, key)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
|
fn serialize_value<T>(&mut self, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
let key = self.next_key.take();
|
let key = self.next_key.take();
|
||||||
// Panic because this indicates a bug in the program rather than an
|
// Panic because this indicates a bug in the program rather than an
|
||||||
|
@ -326,7 +344,8 @@ impl<'lua> serde::ser::SerializeStruct for SerializeMap<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
serde::ser::SerializeMap::serialize_key(self, key)?;
|
serde::ser::SerializeMap::serialize_key(self, key)?;
|
||||||
serde::ser::SerializeMap::serialize_value(self, value)
|
serde::ser::SerializeMap::serialize_value(self, value)
|
||||||
|
@ -337,7 +356,6 @@ impl<'lua> serde::ser::SerializeStruct for SerializeMap<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct SerializeStructVariant<'lua> {
|
pub struct SerializeStructVariant<'lua> {
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
name: LuaString<'lua>,
|
name: LuaString<'lua>,
|
||||||
|
@ -349,10 +367,10 @@ impl<'lua> serde::ser::SerializeStructVariant for SerializeStructVariant<'lua> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
|
||||||
where T: ?Sized + serde::Serialize,
|
where
|
||||||
|
T: ?Sized + serde::Serialize,
|
||||||
{
|
{
|
||||||
self.table
|
self.table.set(key, to_value(self.lua, value)?)?;
|
||||||
.set(key, to_value(self.lua, value)?)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,8 +383,8 @@ impl<'lua> serde::ser::SerializeStructVariant for SerializeStructVariant<'lua> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use mlua::Lua;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use mlua::Lua;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_struct() {
|
fn test_struct() {
|
||||||
|
@ -376,19 +394,23 @@ mod tests {
|
||||||
seq: Vec<&'static str>,
|
seq: Vec<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let test = Test { int: 1, seq: vec!["a", "b"] };
|
let test = Test {
|
||||||
|
int: 1,
|
||||||
|
seq: vec!["a", "b"],
|
||||||
|
};
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
lua.context(|lua| {
|
let value = to_value(&lua, &test).unwrap();
|
||||||
let value = to_value(lua, &test).unwrap();
|
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(
|
lua.load(
|
||||||
r#"
|
r#"
|
||||||
assert(value["int"] == 1)
|
assert(value["int"] == 1)
|
||||||
assert(value["seq"][1] == "a")
|
assert(value["seq"][1] == "a")
|
||||||
assert(value["seq"][2] == "b")
|
assert(value["seq"][2] == "b")
|
||||||
"#).exec()
|
"#,
|
||||||
}).unwrap()
|
)
|
||||||
|
.exec()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -398,40 +420,54 @@ mod tests {
|
||||||
Unit,
|
Unit,
|
||||||
Newtype(u32),
|
Newtype(u32),
|
||||||
Tuple(u32, u32),
|
Tuple(u32, u32),
|
||||||
Struct { a: u32},
|
Struct { a: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
||||||
lua.context(|lua| {
|
|
||||||
let u = E::Unit;
|
let u = E::Unit;
|
||||||
let value = to_value(lua, &u).unwrap();
|
let value = to_value(&lua, &u).unwrap();
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(r#"
|
lua.load(
|
||||||
|
r#"
|
||||||
assert(value == "Unit")
|
assert(value == "Unit")
|
||||||
"#).exec().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let n = E::Newtype(1);
|
let n = E::Newtype(1);
|
||||||
let value = to_value(lua, &n).unwrap();
|
let value = to_value(&lua, &n).unwrap();
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(r#"
|
lua.load(
|
||||||
|
r#"
|
||||||
assert(value["Newtype"] == 1)
|
assert(value["Newtype"] == 1)
|
||||||
"#).exec().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let t = E::Tuple(1, 2);
|
let t = E::Tuple(1, 2);
|
||||||
let value = to_value(lua, &t).unwrap();
|
let value = to_value(&lua, &t).unwrap();
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(r#"
|
lua.load(
|
||||||
|
r#"
|
||||||
assert(value["Tuple"][1] == 1)
|
assert(value["Tuple"][1] == 1)
|
||||||
assert(value["Tuple"][2] == 2)
|
assert(value["Tuple"][2] == 2)
|
||||||
"#).exec().unwrap();
|
"#,
|
||||||
|
)
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let s = E::Struct { a: 1 };
|
let s = E::Struct { a: 1 };
|
||||||
let value = to_value(lua, &s).unwrap();
|
let value = to_value(&lua, &s).unwrap();
|
||||||
lua.globals().set("value", value).unwrap();
|
lua.globals().set("value", value).unwrap();
|
||||||
lua.load(r#"
|
lua.load(
|
||||||
|
r#"
|
||||||
assert(value["Struct"]["a"] == 1)
|
assert(value["Struct"]["a"] == 1)
|
||||||
"#).exec()
|
"#,
|
||||||
}).unwrap();
|
)
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue