1use serde::{Serialize, ser};
4
5use super::LuaSerdeExt;
6use crate::error::{Error, Result};
7use crate::state::Lua;
8use crate::table::Table;
9use crate::traits::IntoLua;
10use crate::value::Value;
11
12#[derive(Debug)]
14pub struct Serializer<'a> {
15 lua: &'a Lua,
16 options: Options,
17}
18
19#[derive(Debug, Clone, Copy)]
21#[non_exhaustive]
22pub struct Options {
23 pub recursion_limit: usize,
29
30 pub set_array_metatable: bool,
37
38 pub serialize_none_to_null: bool,
46
47 pub serialize_unit_to_null: bool,
55
56 pub detect_serde_json_arbitrary_precision: bool,
61}
62
63impl Default for Options {
64 fn default() -> Self {
65 const { Self::new() }
66 }
67}
68
69impl Options {
70 pub const fn new() -> Self {
72 Options {
73 recursion_limit: super::DEFAULT_RECURSION_LIMIT,
74 set_array_metatable: true,
75 serialize_none_to_null: true,
76 serialize_unit_to_null: true,
77 detect_serde_json_arbitrary_precision: false,
78 }
79 }
80
81 #[must_use]
85 pub const fn recursion_limit(mut self, limit: usize) -> Self {
86 self.recursion_limit = limit;
87 self
88 }
89
90 #[must_use]
94 pub const fn set_array_metatable(mut self, enabled: bool) -> Self {
95 self.set_array_metatable = enabled;
96 self
97 }
98
99 #[must_use]
103 pub const fn serialize_none_to_null(mut self, enabled: bool) -> Self {
104 self.serialize_none_to_null = enabled;
105 self
106 }
107
108 #[must_use]
112 pub const fn serialize_unit_to_null(mut self, enabled: bool) -> Self {
113 self.serialize_unit_to_null = enabled;
114 self
115 }
116
117 #[must_use]
126 pub const fn detect_serde_json_arbitrary_precision(mut self, enabled: bool) -> Self {
127 self.detect_serde_json_arbitrary_precision = enabled;
128 self
129 }
130}
131
132impl<'a> Serializer<'a> {
133 pub fn new(lua: &'a Lua) -> Self {
135 Self::new_with_options(lua, Options::default())
136 }
137
138 pub fn new_with_options(lua: &'a Lua, options: Options) -> Self {
140 Serializer { lua, options }
141 }
142
143 #[inline]
144 fn descend(mut self) -> Result<Self> {
145 self.options.recursion_limit = (self.options)
146 .recursion_limit
147 .checked_sub(1)
148 .ok_or_else(|| Error::SerializeError("recursion limit exceeded".into()))?;
149 Ok(self)
150 }
151}
152
153macro_rules! lua_serialize_number {
154 ($name:ident, $t:ty) => {
155 #[inline]
156 fn $name(self, value: $t) -> Result<Value> {
157 value.into_lua(self.lua)
158 }
159 };
160}
161
162impl<'a> ser::Serializer for Serializer<'a> {
163 type Ok = Value;
164 type Error = Error;
165
166 type SerializeSeq = SerializeSeq<'a>;
169 type SerializeTuple = SerializeSeq<'a>;
170 type SerializeTupleStruct = SerializeSeq<'a>;
171 type SerializeTupleVariant = SerializeTupleVariant<'a>;
172 type SerializeMap = SerializeMap<'a>;
173 type SerializeStruct = SerializeStruct<'a>;
174 type SerializeStructVariant = SerializeStructVariant<'a>;
175
176 #[inline]
177 fn serialize_bool(self, value: bool) -> Result<Value> {
178 Ok(Value::Boolean(value))
179 }
180
181 lua_serialize_number!(serialize_i8, i8);
182 lua_serialize_number!(serialize_u8, u8);
183 lua_serialize_number!(serialize_i16, i16);
184 lua_serialize_number!(serialize_u16, u16);
185 lua_serialize_number!(serialize_i32, i32);
186 lua_serialize_number!(serialize_u32, u32);
187 lua_serialize_number!(serialize_i64, i64);
188 lua_serialize_number!(serialize_u64, u64);
189 lua_serialize_number!(serialize_i128, i128);
190 lua_serialize_number!(serialize_u128, u128);
191
192 lua_serialize_number!(serialize_f32, f32);
193 lua_serialize_number!(serialize_f64, f64);
194
195 #[inline]
196 fn serialize_char(self, value: char) -> Result<Value> {
197 self.serialize_str(value.encode_utf8(&mut [0; 4]))
198 }
199
200 #[inline]
201 fn serialize_str(self, value: &str) -> Result<Value> {
202 self.lua.create_string(value).map(Value::String)
203 }
204
205 #[inline]
206 fn serialize_bytes(self, value: &[u8]) -> Result<Value> {
207 self.lua.create_string(value).map(Value::String)
208 }
209
210 #[inline]
211 fn serialize_none(self) -> Result<Value> {
212 if self.options.serialize_none_to_null {
213 Ok(self.lua.null())
214 } else {
215 Ok(Value::Nil)
216 }
217 }
218
219 #[inline]
220 fn serialize_some<T>(self, value: &T) -> Result<Value>
221 where
222 T: Serialize + ?Sized,
223 {
224 value.serialize(self.descend()?)
225 }
226
227 #[inline]
228 fn serialize_unit(self) -> Result<Value> {
229 if self.options.serialize_unit_to_null {
230 Ok(self.lua.null())
231 } else {
232 Ok(Value::Nil)
233 }
234 }
235
236 #[inline]
237 fn serialize_unit_struct(self, _name: &'static str) -> Result<Value> {
238 if self.options.serialize_unit_to_null {
239 Ok(self.lua.null())
240 } else {
241 Ok(Value::Nil)
242 }
243 }
244
245 #[inline]
246 fn serialize_unit_variant(
247 self,
248 _name: &'static str,
249 _variant_index: u32,
250 variant: &'static str,
251 ) -> Result<Value> {
252 self.serialize_str(variant)
253 }
254
255 #[inline]
256 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Value>
257 where
258 T: Serialize + ?Sized,
259 {
260 value.serialize(self.descend()?)
261 }
262
263 #[inline]
264 fn serialize_newtype_variant<T>(
265 mut self,
266 _name: &'static str,
267 _variant_index: u32,
268 variant: &'static str,
269 value: &T,
270 ) -> Result<Value>
271 where
272 T: Serialize + ?Sized,
273 {
274 self = self.descend()?;
275 let variant = self.lua.create_string(variant)?;
276 let value = self.lua.to_value_with(value, self.options)?;
277 let table = (self.lua).create_table_with_capacity(0, usize::from(!value.is_nil()))?;
278 table.raw_set(variant, value)?;
279 Ok(Value::Table(table))
280 }
281
282 #[inline]
283 fn serialize_seq(mut self, len: Option<usize>) -> Result<Self::SerializeSeq> {
284 self = self.descend()?;
285 let table = self.lua.create_table_with_capacity(len.unwrap_or(0), 0)?;
286 if self.options.set_array_metatable {
287 let lua = self.lua.lock();
288 unsafe {
289 super::push_array_metatable(lua.ref_thread());
290 ffi::lua_setmetatable(lua.ref_thread(), table.0.index);
291 }
292 }
293 Ok(SerializeSeq::new(self.lua, table, self.options))
294 }
295
296 #[inline]
297 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
298 self.serialize_seq(Some(len))
299 }
300
301 #[inline]
302 fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct> {
303 #[cfg(feature = "luau")]
304 if name == "Vector" && len == crate::Vector::SIZE {
305 let this = self.descend()?;
306 return Ok(SerializeSeq::new_vector(this.lua, this.options));
307 }
308 _ = name;
309 self.serialize_seq(Some(len))
310 }
311
312 #[inline]
313 fn serialize_tuple_variant(
314 mut self,
315 _name: &'static str,
316 _variant_index: u32,
317 variant: &'static str,
318 len: usize,
319 ) -> Result<Self::SerializeTupleVariant> {
320 self = self.descend()?;
321 let capacity = if self.options.serialize_none_to_null && self.options.serialize_unit_to_null {
322 len
323 } else {
324 0
325 };
326 Ok(SerializeTupleVariant {
327 lua: self.lua,
328 variant,
329 table: self.lua.create_table_with_capacity(capacity, 0)?,
330 options: self.options,
331 })
332 }
333
334 #[inline]
335 fn serialize_map(mut self, len: Option<usize>) -> Result<Self::SerializeMap> {
336 self = self.descend()?;
337 Ok(SerializeMap {
338 lua: self.lua,
339 key: None,
340 table: self.lua.create_table_with_capacity(0, len.unwrap_or(0))?,
341 options: self.options,
342 })
343 }
344
345 #[inline]
346 fn serialize_struct(mut self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
347 self = self.descend()?;
348 if self.options.detect_serde_json_arbitrary_precision
349 && name == "$serde_json::private::Number"
350 && len == 1
351 {
352 return Ok(SerializeStruct {
353 lua: self.lua,
354 inner: None,
355 options: self.options,
356 });
357 }
358
359 Ok(SerializeStruct {
360 lua: self.lua,
361 inner: Some(Value::Table(self.lua.create_table_with_capacity(0, len)?)),
362 options: self.options,
363 })
364 }
365
366 #[inline]
367 fn serialize_struct_variant(
368 mut self,
369 _name: &'static str,
370 _variant_index: u32,
371 variant: &'static str,
372 len: usize,
373 ) -> Result<Self::SerializeStructVariant> {
374 self = self.descend()?;
375 Ok(SerializeStructVariant {
376 lua: self.lua,
377 variant,
378 table: self.lua.create_table_with_capacity(0, len)?,
379 options: self.options,
380 })
381 }
382}
383
384#[doc(hidden)]
385pub struct SerializeSeq<'a> {
386 lua: &'a Lua,
387 #[cfg(feature = "luau")]
388 vector: Option<crate::Vector>,
389 table: Option<Table>,
390 next: usize,
391 options: Options,
392}
393
394impl<'a> SerializeSeq<'a> {
395 fn new(lua: &'a Lua, table: Table, options: Options) -> Self {
396 Self {
397 lua,
398 #[cfg(feature = "luau")]
399 vector: None,
400 table: Some(table),
401 next: 0,
402 options,
403 }
404 }
405
406 #[cfg(feature = "luau")]
407 const fn new_vector(lua: &'a Lua, options: Options) -> Self {
408 Self {
409 lua,
410 vector: Some(crate::Vector::zero()),
411 table: None,
412 next: 0,
413 options,
414 }
415 }
416}
417
418impl ser::SerializeSeq for SerializeSeq<'_> {
419 type Ok = Value;
420 type Error = Error;
421
422 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
423 where
424 T: Serialize + ?Sized,
425 {
426 let value = self.lua.to_value_with(value, self.options)?;
427 let table = self.table.as_ref().unwrap();
428 table.raw_seti(self.next + 1, value)?;
429 self.next += 1;
430 Ok(())
431 }
432
433 fn end(self) -> Result<Value> {
434 Ok(Value::Table(self.table.unwrap()))
435 }
436}
437
438impl ser::SerializeTuple for SerializeSeq<'_> {
439 type Ok = Value;
440 type Error = Error;
441
442 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
443 where
444 T: Serialize + ?Sized,
445 {
446 ser::SerializeSeq::serialize_element(self, value)
447 }
448
449 fn end(self) -> Result<Value> {
450 ser::SerializeSeq::end(self)
451 }
452}
453
454impl ser::SerializeTupleStruct for SerializeSeq<'_> {
455 type Ok = Value;
456 type Error = Error;
457
458 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
459 where
460 T: Serialize + ?Sized,
461 {
462 #[cfg(feature = "luau")]
463 if let Some(vector) = self.vector.as_mut() {
464 let value = self.lua.to_value_with(value, self.options)?;
465 let value = self.lua.unpack(value)?;
466 vector.0[self.next] = value;
467 self.next += 1;
468 return Ok(());
469 }
470 ser::SerializeSeq::serialize_element(self, value)
471 }
472
473 fn end(self) -> Result<Value> {
474 #[cfg(feature = "luau")]
475 if let Some(vector) = self.vector {
476 return Ok(Value::Vector(vector));
477 }
478 ser::SerializeSeq::end(self)
479 }
480}
481
482#[doc(hidden)]
483pub struct SerializeTupleVariant<'a> {
484 lua: &'a Lua,
485 variant: &'static str,
486 table: Table,
487 options: Options,
488}
489
490impl ser::SerializeTupleVariant for SerializeTupleVariant<'_> {
491 type Ok = Value;
492 type Error = Error;
493
494 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
495 where
496 T: Serialize + ?Sized,
497 {
498 self.table.raw_push(self.lua.to_value_with(value, self.options)?)
499 }
500
501 fn end(self) -> Result<Value> {
502 let table = self.lua.create_table_with_capacity(0, 1)?;
503 table.raw_set(self.variant, self.table)?;
504 Ok(Value::Table(table))
505 }
506}
507
508#[doc(hidden)]
509pub struct SerializeMap<'a> {
510 lua: &'a Lua,
511 table: Table,
512 key: Option<Value>,
513 options: Options,
514}
515
516impl ser::SerializeMap for SerializeMap<'_> {
517 type Ok = Value;
518 type Error = Error;
519
520 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
521 where
522 T: Serialize + ?Sized,
523 {
524 self.key = Some(self.lua.to_value_with(key, self.options)?);
525 Ok(())
526 }
527
528 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
529 where
530 T: Serialize + ?Sized,
531 {
532 let key = mlua_expect!(self.key.take(), "serialize_value called before serialize_key");
533 let value = self.lua.to_value_with(value, self.options)?;
534 self.table.raw_set(key, value)
535 }
536
537 fn end(self) -> Result<Value> {
538 Ok(Value::Table(self.table))
539 }
540}
541
542#[doc(hidden)]
543pub struct SerializeStruct<'a> {
544 lua: &'a Lua,
545 inner: Option<Value>,
546 options: Options,
547}
548
549impl ser::SerializeStruct for SerializeStruct<'_> {
550 type Ok = Value;
551 type Error = Error;
552
553 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
554 where
555 T: Serialize + ?Sized,
556 {
557 match self.inner {
558 Some(Value::Table(ref table)) => {
559 table.raw_set(key, self.lua.to_value_with(value, self.options)?)?;
560 }
561 None if self.options.detect_serde_json_arbitrary_precision => {
562 assert_eq!(key, "$serde_json::private::Number");
564 self.inner = Some(self.lua.to_value_with(value, self.options)?);
565 }
566 _ => unreachable!(),
567 }
568 Ok(())
569 }
570
571 fn end(self) -> Result<Value> {
572 match self.inner {
573 Some(table @ Value::Table(_)) => Ok(table),
574 Some(value @ Value::String(_)) if self.options.detect_serde_json_arbitrary_precision => {
575 let number_s = value.to_string()?;
576 if number_s.contains(['.', 'e', 'E'])
577 && let Ok(number) = number_s.parse().map(Value::Number)
578 {
579 return Ok(number);
580 }
581 Ok(number_s
582 .parse()
583 .map(Value::Integer)
584 .or_else(|_| number_s.parse().map(Value::Number))
585 .unwrap_or(value))
586 }
587 _ => unreachable!(),
588 }
589 }
590}
591
592#[doc(hidden)]
593pub struct SerializeStructVariant<'a> {
594 lua: &'a Lua,
595 variant: &'static str,
596 table: Table,
597 options: Options,
598}
599
600impl ser::SerializeStructVariant for SerializeStructVariant<'_> {
601 type Ok = Value;
602 type Error = Error;
603
604 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
605 where
606 T: Serialize + ?Sized,
607 {
608 self.table
609 .raw_set(key, self.lua.to_value_with(value, self.options)?)?;
610 Ok(())
611 }
612
613 fn end(self) -> Result<Value> {
614 let table = self.lua.create_table_with_capacity(0, 1)?;
615 table.raw_set(self.variant, self.table)?;
616 Ok(Value::Table(table))
617 }
618}