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