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