1use std::os::raw::c_int;
2
3use serde::{ser, Serialize};
4
5use super::LuaSerdeExt;
6use crate::error::{Error, Result};
7use crate::ffi;
8use crate::lua::Lua;
9use crate::string::String;
10use crate::table::Table;
11use crate::types::Integer;
12use crate::util::{check_stack, StackGuard};
13use crate::value::{ToLua, Value};
14
15#[derive(Debug)]
17pub struct Serializer<'lua> {
18 lua: &'lua Lua,
19 options: Options,
20}
21
22#[derive(Debug, Clone, Copy)]
24#[non_exhaustive]
25pub struct Options {
26 pub set_array_metatable: bool,
33
34 pub serialize_none_to_null: bool,
42
43 pub serialize_unit_to_null: bool,
51}
52
53impl Default for Options {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl Options {
60 pub const fn new() -> Self {
62 Options {
63 set_array_metatable: true,
64 serialize_none_to_null: true,
65 serialize_unit_to_null: true,
66 }
67 }
68
69 #[must_use]
73 pub const fn set_array_metatable(mut self, enabled: bool) -> Self {
74 self.set_array_metatable = enabled;
75 self
76 }
77
78 #[must_use]
82 pub const fn serialize_none_to_null(mut self, enabled: bool) -> Self {
83 self.serialize_none_to_null = enabled;
84 self
85 }
86
87 #[must_use]
91 pub const fn serialize_unit_to_null(mut self, enabled: bool) -> Self {
92 self.serialize_unit_to_null = enabled;
93 self
94 }
95}
96
97impl<'lua> Serializer<'lua> {
98 pub fn new(lua: &'lua Lua) -> Self {
100 Self::new_with_options(lua, Options::default())
101 }
102
103 pub fn new_with_options(lua: &'lua Lua, options: Options) -> Self {
105 Serializer { lua, options }
106 }
107}
108
109macro_rules! lua_serialize_number {
110 ($name:ident, $t:ty) => {
111 #[inline]
112 fn $name(self, value: $t) -> Result<Value<'lua>> {
113 value.to_lua(self.lua)
114 }
115 };
116}
117
118impl<'lua> ser::Serializer for Serializer<'lua> {
119 type Ok = Value<'lua>;
120 type Error = Error;
121
122 type SerializeSeq = SerializeVec<'lua>;
125 type SerializeTuple = SerializeVec<'lua>;
126 type SerializeTupleStruct = SerializeVec<'lua>;
127 type SerializeTupleVariant = SerializeTupleVariant<'lua>;
128 type SerializeMap = SerializeMap<'lua>;
129 type SerializeStruct = SerializeMap<'lua>;
130 type SerializeStructVariant = SerializeStructVariant<'lua>;
131
132 #[inline]
133 fn serialize_bool(self, value: bool) -> Result<Value<'lua>> {
134 Ok(Value::Boolean(value))
135 }
136
137 lua_serialize_number!(serialize_i8, i8);
138 lua_serialize_number!(serialize_u8, u8);
139 lua_serialize_number!(serialize_i16, i16);
140 lua_serialize_number!(serialize_u16, u16);
141 lua_serialize_number!(serialize_i32, i32);
142 lua_serialize_number!(serialize_u32, u32);
143 lua_serialize_number!(serialize_i64, i64);
144 lua_serialize_number!(serialize_u64, u64);
145 lua_serialize_number!(serialize_i128, i128);
146 lua_serialize_number!(serialize_u128, u128);
147
148 lua_serialize_number!(serialize_f32, f32);
149 lua_serialize_number!(serialize_f64, f64);
150
151 #[inline]
152 fn serialize_char(self, value: char) -> Result<Value<'lua>> {
153 self.serialize_str(&value.to_string())
154 }
155
156 #[inline]
157 fn serialize_str(self, value: &str) -> Result<Value<'lua>> {
158 self.lua.create_string(value).map(Value::String)
159 }
160
161 #[inline]
162 fn serialize_bytes(self, value: &[u8]) -> Result<Value<'lua>> {
163 self.lua.create_string(value).map(Value::String)
164 }
165
166 #[inline]
167 fn serialize_none(self) -> Result<Value<'lua>> {
168 if self.options.serialize_none_to_null {
169 Ok(self.lua.null())
170 } else {
171 Ok(Value::Nil)
172 }
173 }
174
175 #[inline]
176 fn serialize_some<T>(self, value: &T) -> Result<Value<'lua>>
177 where
178 T: Serialize + ?Sized,
179 {
180 value.serialize(self)
181 }
182
183 #[inline]
184 fn serialize_unit(self) -> Result<Value<'lua>> {
185 if self.options.serialize_unit_to_null {
186 Ok(self.lua.null())
187 } else {
188 Ok(Value::Nil)
189 }
190 }
191
192 #[inline]
193 fn serialize_unit_struct(self, _name: &'static str) -> Result<Value<'lua>> {
194 if self.options.serialize_unit_to_null {
195 Ok(self.lua.null())
196 } else {
197 Ok(Value::Nil)
198 }
199 }
200
201 #[inline]
202 fn serialize_unit_variant(
203 self,
204 _name: &'static str,
205 _variant_index: u32,
206 variant: &'static str,
207 ) -> Result<Value<'lua>> {
208 self.serialize_str(variant)
209 }
210
211 #[inline]
212 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value<'lua>>
213 where
214 T: Serialize + ?Sized,
215 {
216 value.serialize(self)
217 }
218
219 #[inline]
220 fn serialize_newtype_variant<T>(
221 self,
222 _name: &'static str,
223 _variant_index: u32,
224 variant: &'static str,
225 value: &T,
226 ) -> Result<Value<'lua>>
227 where
228 T: Serialize + ?Sized,
229 {
230 let table = self.lua.create_table()?;
231 let variant = self.lua.create_string(variant)?;
232 let value = self.lua.to_value_with(value, self.options)?;
233 table.raw_set(variant, value)?;
234 Ok(Value::Table(table))
235 }
236
237 #[inline]
238 fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
239 let len = len.unwrap_or(0) as c_int;
240 let table = self.lua.create_table_with_capacity(len, 0)?;
241 if self.options.set_array_metatable {
242 table.set_metatable(Some(self.lua.array_metatable()));
243 }
244 let options = self.options;
245 Ok(SerializeVec { table, options })
246 }
247
248 #[inline]
249 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
250 self.serialize_seq(Some(len))
251 }
252
253 #[inline]
254 fn serialize_tuple_struct(
255 self,
256 _name: &'static str,
257 len: usize,
258 ) -> Result<Self::SerializeTupleStruct> {
259 self.serialize_seq(Some(len))
260 }
261
262 #[inline]
263 fn serialize_tuple_variant(
264 self,
265 _name: &'static str,
266 _variant_index: u32,
267 variant: &'static str,
268 _len: usize,
269 ) -> Result<Self::SerializeTupleVariant> {
270 Ok(SerializeTupleVariant {
271 name: self.lua.create_string(variant)?,
272 table: self.lua.create_table()?,
273 options: self.options,
274 })
275 }
276
277 #[inline]
278 fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
279 let len = len.unwrap_or(0) as c_int;
280 Ok(SerializeMap {
281 key: None,
282 table: self.lua.create_table_with_capacity(0, len)?,
283 options: self.options,
284 })
285 }
286
287 #[inline]
288 fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
289 self.serialize_map(Some(len))
290 }
291
292 #[inline]
293 fn serialize_struct_variant(
294 self,
295 _name: &'static str,
296 _variant_index: u32,
297 variant: &'static str,
298 len: usize,
299 ) -> Result<Self::SerializeStructVariant> {
300 Ok(SerializeStructVariant {
301 name: self.lua.create_string(variant)?,
302 table: self.lua.create_table_with_capacity(0, len as c_int)?,
303 options: self.options,
304 })
305 }
306}
307
308#[doc(hidden)]
309pub struct SerializeVec<'lua> {
310 table: Table<'lua>,
311 options: Options,
312}
313
314impl<'lua> ser::SerializeSeq for SerializeVec<'lua> {
315 type Ok = Value<'lua>;
316 type Error = Error;
317
318 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
319 where
320 T: Serialize + ?Sized,
321 {
322 let lua = self.table.0.lua;
323 let value = lua.to_value_with(value, self.options)?;
324 unsafe {
325 let _sg = StackGuard::new(lua.state);
326 check_stack(lua.state, 4)?;
327
328 lua.push_ref(&self.table.0);
329 lua.push_value(value)?;
330 if lua.unlikely_memory_error() {
331 let len = ffi::lua_rawlen(lua.state, -2) as Integer;
332 ffi::lua_rawseti(lua.state, -2, len + 1);
333 ffi::lua_pop(lua.state, 1);
334 Ok(())
335 } else {
336 protect_lua!(lua.state, 2, 0, fn(state) {
337 let len = ffi::lua_rawlen(state, -2) as Integer;
338 ffi::lua_rawseti(state, -2, len + 1);
339 })
340 }
341 }
342 }
343
344 fn end(self) -> Result<Value<'lua>> {
345 Ok(Value::Table(self.table))
346 }
347}
348
349impl<'lua> ser::SerializeTuple for SerializeVec<'lua> {
350 type Ok = Value<'lua>;
351 type Error = Error;
352
353 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
354 where
355 T: Serialize + ?Sized,
356 {
357 ser::SerializeSeq::serialize_element(self, value)
358 }
359
360 fn end(self) -> Result<Value<'lua>> {
361 ser::SerializeSeq::end(self)
362 }
363}
364
365impl<'lua> ser::SerializeTupleStruct for SerializeVec<'lua> {
366 type Ok = Value<'lua>;
367 type Error = Error;
368
369 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
370 where
371 T: Serialize + ?Sized,
372 {
373 ser::SerializeSeq::serialize_element(self, value)
374 }
375
376 fn end(self) -> Result<Value<'lua>> {
377 ser::SerializeSeq::end(self)
378 }
379}
380
381#[doc(hidden)]
382pub struct SerializeTupleVariant<'lua> {
383 name: String<'lua>,
384 table: Table<'lua>,
385 options: Options,
386}
387
388impl<'lua> ser::SerializeTupleVariant for SerializeTupleVariant<'lua> {
389 type Ok = Value<'lua>;
390 type Error = Error;
391
392 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
393 where
394 T: Serialize + ?Sized,
395 {
396 let lua = self.table.0.lua;
397 let idx = self.table.raw_len() + 1;
398 self.table
399 .raw_insert(idx, lua.to_value_with(value, self.options)?)
400 }
401
402 fn end(self) -> Result<Value<'lua>> {
403 let lua = self.table.0.lua;
404 let table = lua.create_table()?;
405 table.raw_set(self.name, self.table)?;
406 Ok(Value::Table(table))
407 }
408}
409
410#[doc(hidden)]
411pub struct SerializeMap<'lua> {
412 table: Table<'lua>,
413 key: Option<Value<'lua>>,
414 options: Options,
415}
416
417impl<'lua> ser::SerializeMap for SerializeMap<'lua> {
418 type Ok = Value<'lua>;
419 type Error = Error;
420
421 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
422 where
423 T: Serialize + ?Sized,
424 {
425 let lua = self.table.0.lua;
426 self.key = Some(lua.to_value_with(key, self.options)?);
427 Ok(())
428 }
429
430 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
431 where
432 T: Serialize + ?Sized,
433 {
434 let lua = self.table.0.lua;
435 let key = mlua_expect!(
436 self.key.take(),
437 "serialize_value called before serialize_key"
438 );
439 let value = lua.to_value_with(value, self.options)?;
440 self.table.raw_set(key, value)
441 }
442
443 fn end(self) -> Result<Value<'lua>> {
444 Ok(Value::Table(self.table))
445 }
446}
447
448impl<'lua> ser::SerializeStruct for SerializeMap<'lua> {
449 type Ok = Value<'lua>;
450 type Error = Error;
451
452 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
453 where
454 T: Serialize + ?Sized,
455 {
456 ser::SerializeMap::serialize_key(self, key)?;
457 ser::SerializeMap::serialize_value(self, value)
458 }
459
460 fn end(self) -> Result<Value<'lua>> {
461 ser::SerializeMap::end(self)
462 }
463}
464
465#[doc(hidden)]
466pub struct SerializeStructVariant<'lua> {
467 name: String<'lua>,
468 table: Table<'lua>,
469 options: Options,
470}
471
472impl<'lua> ser::SerializeStructVariant for SerializeStructVariant<'lua> {
473 type Ok = Value<'lua>;
474 type Error = Error;
475
476 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
477 where
478 T: Serialize + ?Sized,
479 {
480 let lua = self.table.0.lua;
481 self.table
482 .raw_set(key, lua.to_value_with(value, self.options)?)?;
483 Ok(())
484 }
485
486 fn end(self) -> Result<Value<'lua>> {
487 let lua = self.table.0.lua;
488 let table = lua.create_table()?;
489 table.raw_set(self.name, self.table)?;
490 Ok(Value::Table(table))
491 }
492}