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