1use std::cell::RefCell;
4use std::os::raw::c_void;
5use std::rc::Rc;
6use std::result::Result as StdResult;
7
8use rustc_hash::FxHashSet;
9use serde::de::{self, IntoDeserializer};
10
11use crate::error::{Error, Result};
12use crate::table::{Table, TablePairs, TableSequence};
13use crate::userdata::AnyUserData;
14use crate::value::Value;
15
16#[derive(Debug, Default)]
18pub struct Deserializer {
19 value: Value,
20 options: Options,
21 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
22 len: Option<usize>, }
24
25#[derive(Debug, Clone, Copy)]
27#[non_exhaustive]
28pub struct Options {
29 pub deny_unsupported_types: bool,
40
41 pub deny_recursive_tables: bool,
47
48 pub sort_keys: bool,
52
53 pub encode_empty_tables_as_array: bool,
57
58 pub detect_mixed_tables: bool,
70}
71
72impl Default for Options {
73 fn default() -> Self {
74 const { Self::new() }
75 }
76}
77
78impl Options {
79 pub const fn new() -> Self {
81 Options {
82 deny_unsupported_types: true,
83 deny_recursive_tables: true,
84 sort_keys: false,
85 encode_empty_tables_as_array: false,
86 detect_mixed_tables: false,
87 }
88 }
89
90 #[must_use]
94 pub const fn deny_unsupported_types(mut self, enabled: bool) -> Self {
95 self.deny_unsupported_types = enabled;
96 self
97 }
98
99 #[must_use]
103 pub const fn deny_recursive_tables(mut self, enabled: bool) -> Self {
104 self.deny_recursive_tables = enabled;
105 self
106 }
107
108 #[must_use]
112 pub const fn sort_keys(mut self, enabled: bool) -> Self {
113 self.sort_keys = enabled;
114 self
115 }
116
117 #[must_use]
121 pub const fn encode_empty_tables_as_array(mut self, enabled: bool) -> Self {
122 self.encode_empty_tables_as_array = enabled;
123 self
124 }
125
126 #[must_use]
130 pub const fn detect_mixed_tables(mut self, enable: bool) -> Self {
131 self.detect_mixed_tables = enable;
132 self
133 }
134}
135
136impl Deserializer {
137 pub fn new(value: Value) -> Self {
139 Self::new_with_options(value, Options::default())
140 }
141
142 pub fn new_with_options(value: Value, options: Options) -> Self {
144 Deserializer {
145 value,
146 options,
147 ..Default::default()
148 }
149 }
150
151 fn from_parts(value: Value, options: Options, visited: Rc<RefCell<FxHashSet<*const c_void>>>) -> Self {
152 Deserializer {
153 value,
154 options,
155 visited,
156 ..Default::default()
157 }
158 }
159
160 fn with_len(mut self, len: usize) -> Self {
161 self.len = Some(len);
162 self
163 }
164}
165
166impl<'de> serde::Deserializer<'de> for Deserializer {
167 type Error = Error;
168
169 #[inline]
170 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
171 where
172 V: de::Visitor<'de>,
173 {
174 match self.value {
175 Value::Nil => visitor.visit_unit(),
176 Value::Boolean(b) => visitor.visit_bool(b),
177 #[allow(clippy::useless_conversion)]
178 Value::Integer(i) => visitor.visit_i64(i.into()),
179 #[allow(clippy::useless_conversion)]
180 Value::Number(n) => visitor.visit_f64(n.into()),
181 #[cfg(feature = "luau")]
182 Value::Vector(_) => self.deserialize_seq(visitor),
183 Value::String(s) => match s.to_str() {
184 Ok(s) => visitor.visit_str(&s),
185 Err(_) => visitor.visit_bytes(&s.as_bytes()),
186 },
187 Value::Table(ref t) => {
188 if let Some(len) = t.encode_as_array(self.options) {
189 self.with_len(len).deserialize_seq(visitor)
190 } else {
191 self.deserialize_map(visitor)
192 }
193 }
194 Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_none(),
195 Value::UserData(ud) if ud.is_serializable() => {
196 serde_userdata(ud, |value| value.deserialize_any(visitor))
197 }
198 #[cfg(feature = "luau")]
199 Value::Buffer(buf) => {
200 let lua = buf.0.lua.lock();
201 visitor.visit_bytes(buf.as_slice(&lua))
202 }
203 Value::Function(_)
204 | Value::Thread(_)
205 | Value::UserData(_)
206 | Value::LightUserData(_)
207 | Value::Error(_)
208 | Value::Other(_) => {
209 if self.options.deny_unsupported_types {
210 let msg = format!("unsupported value type `{}`", self.value.type_name());
211 Err(de::Error::custom(msg))
212 } else {
213 visitor.visit_unit()
214 }
215 }
216 }
217 }
218
219 #[inline]
220 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
221 where
222 V: de::Visitor<'de>,
223 {
224 match self.value {
225 Value::Nil => visitor.visit_none(),
226 Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_none(),
227 _ => visitor.visit_some(self),
228 }
229 }
230
231 #[inline]
232 fn deserialize_enum<V>(
233 self,
234 name: &'static str,
235 variants: &'static [&'static str],
236 visitor: V,
237 ) -> Result<V::Value>
238 where
239 V: de::Visitor<'de>,
240 {
241 let (variant, value, _guard) = match self.value {
242 Value::Table(table) => {
243 let _guard = RecursionGuard::new(&table, &self.visited);
244
245 let mut iter = table.pairs::<String, Value>();
246 let (variant, value) = match iter.next() {
247 Some(v) => v?,
248 None => {
249 return Err(de::Error::invalid_value(
250 de::Unexpected::Map,
251 &"map with a single key",
252 ));
253 }
254 };
255
256 if iter.next().is_some() {
257 return Err(de::Error::invalid_value(
258 de::Unexpected::Map,
259 &"map with a single key",
260 ));
261 }
262 let skip = check_value_for_skip(&value, self.options, &self.visited)
263 .map_err(|err| Error::DeserializeError(err.to_string()))?;
264 if skip {
265 return Err(de::Error::custom("bad enum value"));
266 }
267
268 (variant, Some(value), Some(_guard))
269 }
270 Value::String(variant) => (variant.to_str()?.to_owned(), None, None),
271 Value::UserData(ud) if ud.is_serializable() => {
272 return serde_userdata(ud, |value| value.deserialize_enum(name, variants, visitor));
273 }
274 _ => return Err(de::Error::custom("bad enum value")),
275 };
276
277 visitor.visit_enum(EnumDeserializer {
278 variant,
279 value,
280 options: self.options,
281 visited: self.visited,
282 })
283 }
284
285 #[inline]
286 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
287 where
288 V: de::Visitor<'de>,
289 {
290 match self.value {
291 #[cfg(feature = "luau")]
292 Value::Vector(vec) => {
293 let mut deserializer = VecDeserializer {
294 vec,
295 next: 0,
296 options: self.options,
297 visited: self.visited,
298 };
299 visitor.visit_seq(&mut deserializer)
300 }
301 Value::Table(t) => {
302 let _guard = RecursionGuard::new(&t, &self.visited);
303
304 let len = self.len.unwrap_or_else(|| t.raw_len());
305 let mut deserializer = SeqDeserializer {
306 seq: t.sequence_values().with_len(len),
307 options: self.options,
308 visited: self.visited,
309 };
310 let seq = visitor.visit_seq(&mut deserializer)?;
311 if deserializer.seq.next().is_none() {
312 Ok(seq)
313 } else {
314 Err(de::Error::invalid_length(len, &"fewer elements in the table"))
315 }
316 }
317 Value::UserData(ud) if ud.is_serializable() => {
318 serde_userdata(ud, |value| value.deserialize_seq(visitor))
319 }
320 value => Err(de::Error::invalid_type(
321 de::Unexpected::Other(value.type_name()),
322 &"table",
323 )),
324 }
325 }
326
327 #[inline]
328 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
329 where
330 V: de::Visitor<'de>,
331 {
332 self.deserialize_seq(visitor)
333 }
334
335 #[inline]
336 fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, visitor: V) -> Result<V::Value>
337 where
338 V: de::Visitor<'de>,
339 {
340 self.deserialize_seq(visitor)
341 }
342
343 #[inline]
344 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
345 where
346 V: de::Visitor<'de>,
347 {
348 match self.value {
349 Value::Table(t) => {
350 let _guard = RecursionGuard::new(&t, &self.visited);
351
352 let mut deserializer = MapDeserializer {
353 pairs: MapPairs::new(&t, self.options.sort_keys)?,
354 value: None,
355 options: self.options,
356 visited: self.visited,
357 processed: 0,
358 };
359 let map = visitor.visit_map(&mut deserializer)?;
360 let count = deserializer.pairs.count();
361 if count == 0 {
362 Ok(map)
363 } else {
364 Err(de::Error::invalid_length(
365 deserializer.processed + count,
366 &"fewer elements in the table",
367 ))
368 }
369 }
370 Value::UserData(ud) if ud.is_serializable() => {
371 serde_userdata(ud, |value| value.deserialize_map(visitor))
372 }
373 value => Err(de::Error::invalid_type(
374 de::Unexpected::Other(value.type_name()),
375 &"table",
376 )),
377 }
378 }
379
380 #[inline]
381 fn deserialize_struct<V>(
382 self,
383 _name: &'static str,
384 _fields: &'static [&'static str],
385 visitor: V,
386 ) -> Result<V::Value>
387 where
388 V: de::Visitor<'de>,
389 {
390 self.deserialize_map(visitor)
391 }
392
393 #[inline]
394 fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value>
395 where
396 V: de::Visitor<'de>,
397 {
398 match self.value {
399 Value::UserData(ud) if ud.is_serializable() => {
400 serde_userdata(ud, |value| value.deserialize_newtype_struct(name, visitor))
401 }
402 _ => visitor.visit_newtype_struct(self),
403 }
404 }
405
406 #[inline]
407 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
408 where
409 V: de::Visitor<'de>,
410 {
411 match self.value {
412 Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_unit(),
413 _ => self.deserialize_any(visitor),
414 }
415 }
416
417 #[inline]
418 fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
419 where
420 V: de::Visitor<'de>,
421 {
422 match self.value {
423 Value::LightUserData(ud) if ud.0.is_null() => visitor.visit_unit(),
424 _ => self.deserialize_any(visitor),
425 }
426 }
427
428 serde::forward_to_deserialize_any! {
429 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes
430 byte_buf identifier ignored_any
431 }
432}
433
434struct SeqDeserializer<'a> {
435 seq: TableSequence<'a, Value>,
436 options: Options,
437 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
438}
439
440impl<'de> de::SeqAccess<'de> for SeqDeserializer<'_> {
441 type Error = Error;
442
443 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
444 where
445 T: de::DeserializeSeed<'de>,
446 {
447 loop {
448 match self.seq.next() {
449 Some(value) => {
450 let value = value?;
451 let skip = check_value_for_skip(&value, self.options, &self.visited)
452 .map_err(|err| Error::DeserializeError(err.to_string()))?;
453 if skip {
454 continue;
455 }
456 let visited = Rc::clone(&self.visited);
457 let deserializer = Deserializer::from_parts(value, self.options, visited);
458 return seed.deserialize(deserializer).map(Some);
459 }
460 None => return Ok(None),
461 }
462 }
463 }
464
465 fn size_hint(&self) -> Option<usize> {
466 match self.seq.size_hint() {
467 (lower, Some(upper)) if lower == upper => Some(upper),
468 _ => None,
469 }
470 }
471}
472
473#[cfg(feature = "luau")]
474struct VecDeserializer {
475 vec: crate::Vector,
476 next: usize,
477 options: Options,
478 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
479}
480
481#[cfg(feature = "luau")]
482impl<'de> de::SeqAccess<'de> for VecDeserializer {
483 type Error = Error;
484
485 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
486 where
487 T: de::DeserializeSeed<'de>,
488 {
489 match self.vec.0.get(self.next) {
490 Some(&n) => {
491 self.next += 1;
492 let visited = Rc::clone(&self.visited);
493 let deserializer = Deserializer::from_parts(Value::Number(n as _), self.options, visited);
494 seed.deserialize(deserializer).map(Some)
495 }
496 None => Ok(None),
497 }
498 }
499
500 fn size_hint(&self) -> Option<usize> {
501 Some(crate::Vector::SIZE)
502 }
503}
504
505pub(crate) enum MapPairs<'a> {
506 Iter(TablePairs<'a, Value, Value>),
507 Vec(Vec<(Value, Value)>),
508}
509
510impl<'a> MapPairs<'a> {
511 pub(crate) fn new(t: &'a Table, sort_keys: bool) -> Result<Self> {
512 if sort_keys {
513 let mut pairs = t.pairs::<Value, Value>().collect::<Result<Vec<_>>>()?;
514 pairs.sort_by(|(a, _), (b, _)| b.sort_cmp(a)); Ok(MapPairs::Vec(pairs))
516 } else {
517 Ok(MapPairs::Iter(t.pairs::<Value, Value>()))
518 }
519 }
520
521 pub(crate) fn count(self) -> usize {
522 match self {
523 MapPairs::Iter(iter) => iter.count(),
524 MapPairs::Vec(vec) => vec.len(),
525 }
526 }
527
528 pub(crate) fn size_hint(&self) -> (usize, Option<usize>) {
529 match self {
530 MapPairs::Iter(iter) => iter.size_hint(),
531 MapPairs::Vec(vec) => (vec.len(), Some(vec.len())),
532 }
533 }
534}
535
536impl Iterator for MapPairs<'_> {
537 type Item = Result<(Value, Value)>;
538
539 fn next(&mut self) -> Option<Self::Item> {
540 match self {
541 MapPairs::Iter(iter) => iter.next(),
542 MapPairs::Vec(vec) => vec.pop().map(Ok),
543 }
544 }
545}
546
547struct MapDeserializer<'a> {
548 pairs: MapPairs<'a>,
549 value: Option<Value>,
550 options: Options,
551 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
552 processed: usize,
553}
554
555impl MapDeserializer<'_> {
556 fn next_key_deserializer(&mut self) -> Result<Option<Deserializer>> {
557 loop {
558 match self.pairs.next() {
559 Some(item) => {
560 let (key, value) = item?;
561 let skip_key = check_value_for_skip(&key, self.options, &self.visited)
562 .map_err(|err| Error::DeserializeError(err.to_string()))?;
563 let skip_value = check_value_for_skip(&value, self.options, &self.visited)
564 .map_err(|err| Error::DeserializeError(err.to_string()))?;
565 if skip_key || skip_value {
566 continue;
567 }
568 self.processed += 1;
569 self.value = Some(value);
570 let visited = Rc::clone(&self.visited);
571 let key_de = Deserializer::from_parts(key, self.options, visited);
572 return Ok(Some(key_de));
573 }
574 None => return Ok(None),
575 }
576 }
577 }
578
579 fn next_value_deserializer(&mut self) -> Result<Deserializer> {
580 match self.value.take() {
581 Some(value) => {
582 let visited = Rc::clone(&self.visited);
583 Ok(Deserializer::from_parts(value, self.options, visited))
584 }
585 None => Err(de::Error::custom("value is missing")),
586 }
587 }
588}
589
590impl<'de> de::MapAccess<'de> for MapDeserializer<'_> {
591 type Error = Error;
592
593 fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
594 where
595 T: de::DeserializeSeed<'de>,
596 {
597 match self.next_key_deserializer() {
598 Ok(Some(key_de)) => seed.deserialize(key_de).map(Some),
599 Ok(None) => Ok(None),
600 Err(error) => Err(error),
601 }
602 }
603
604 fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value>
605 where
606 T: de::DeserializeSeed<'de>,
607 {
608 match self.next_value_deserializer() {
609 Ok(value_de) => seed.deserialize(value_de),
610 Err(error) => Err(error),
611 }
612 }
613
614 fn size_hint(&self) -> Option<usize> {
615 match self.pairs.size_hint() {
616 (lower, Some(upper)) if lower == upper => Some(upper),
617 _ => None,
618 }
619 }
620}
621
622struct EnumDeserializer {
623 variant: String,
624 value: Option<Value>,
625 options: Options,
626 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
627}
628
629impl<'de> de::EnumAccess<'de> for EnumDeserializer {
630 type Error = Error;
631 type Variant = VariantDeserializer;
632
633 fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant)>
634 where
635 T: de::DeserializeSeed<'de>,
636 {
637 let variant = self.variant.into_deserializer();
638 let variant_access = VariantDeserializer {
639 value: self.value,
640 options: self.options,
641 visited: self.visited,
642 };
643 seed.deserialize(variant).map(|v| (v, variant_access))
644 }
645}
646
647struct VariantDeserializer {
648 value: Option<Value>,
649 options: Options,
650 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
651}
652
653impl<'de> de::VariantAccess<'de> for VariantDeserializer {
654 type Error = Error;
655
656 fn unit_variant(self) -> Result<()> {
657 match self.value {
658 Some(_) => Err(de::Error::invalid_type(
659 de::Unexpected::NewtypeVariant,
660 &"unit variant",
661 )),
662 None => Ok(()),
663 }
664 }
665
666 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
667 where
668 T: de::DeserializeSeed<'de>,
669 {
670 match self.value {
671 Some(value) => seed.deserialize(Deserializer::from_parts(value, self.options, self.visited)),
672 None => Err(de::Error::invalid_type(
673 de::Unexpected::UnitVariant,
674 &"newtype variant",
675 )),
676 }
677 }
678
679 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
680 where
681 V: de::Visitor<'de>,
682 {
683 match self.value {
684 Some(value) => serde::Deserializer::deserialize_seq(
685 Deserializer::from_parts(value, self.options, self.visited),
686 visitor,
687 ),
688 None => Err(de::Error::invalid_type(
689 de::Unexpected::UnitVariant,
690 &"tuple variant",
691 )),
692 }
693 }
694
695 fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
696 where
697 V: de::Visitor<'de>,
698 {
699 match self.value {
700 Some(value) => serde::Deserializer::deserialize_map(
701 Deserializer::from_parts(value, self.options, self.visited),
702 visitor,
703 ),
704 None => Err(de::Error::invalid_type(
705 de::Unexpected::UnitVariant,
706 &"struct variant",
707 )),
708 }
709 }
710}
711
712pub(crate) struct RecursionGuard {
715 ptr: *const c_void,
716 visited: Rc<RefCell<FxHashSet<*const c_void>>>,
717}
718
719impl RecursionGuard {
720 #[inline]
721 pub(crate) fn new(table: &Table, visited: &Rc<RefCell<FxHashSet<*const c_void>>>) -> Self {
722 let visited = Rc::clone(visited);
723 let ptr = table.to_pointer();
724 visited.borrow_mut().insert(ptr);
725 RecursionGuard { ptr, visited }
726 }
727}
728
729impl Drop for RecursionGuard {
730 fn drop(&mut self) {
731 self.visited.borrow_mut().remove(&self.ptr);
732 }
733}
734
735pub(crate) fn check_value_for_skip(
737 value: &Value,
738 options: Options,
739 visited: &RefCell<FxHashSet<*const c_void>>,
740) -> StdResult<bool, &'static str> {
741 match value {
742 Value::Table(table) => {
743 let ptr = table.to_pointer();
744 if visited.borrow().contains(&ptr) {
745 if options.deny_recursive_tables {
746 return Err("recursive table detected");
747 }
748 return Ok(true); }
750 }
751 Value::UserData(ud) if ud.is_serializable() => {}
752 Value::Function(_)
753 | Value::Thread(_)
754 | Value::UserData(_)
755 | Value::LightUserData(_)
756 | Value::Error(_)
757 if !options.deny_unsupported_types =>
758 {
759 return Ok(true); }
761 _ => {}
762 }
763 Ok(false) }
765
766fn serde_userdata<V>(
767 ud: AnyUserData,
768 f: impl FnOnce(serde_value::Value) -> std::result::Result<V, serde_value::DeserializerError>,
769) -> Result<V> {
770 match serde_value::to_value(ud) {
771 Ok(value) => match f(value) {
772 Ok(r) => Ok(r),
773 Err(error) => Err(Error::DeserializeError(error.to_string())),
774 },
775 Err(error) => Err(Error::SerializeError(error.to_string())),
776 }
777}