protodef_parser/
lib.rs

1use linked_hash_map::LinkedHashMap;
2use serde::de;
3use serde::de::{SeqAccess, Unexpected, Visitor};
4use serde::{Deserialize, Deserializer};
5use std::collections::HashMap;
6use std::fmt;
7use std::io::Read;
8
9pub fn read_protocol<R: Read>(reader: R) -> serde_json::Result<Protocol> {
10    serde_json::from_reader(reader)
11}
12
13#[derive(Debug, Eq, PartialEq, Deserialize)]
14pub struct Protocol {
15    pub types: LinkedHashMap<String, DataType>,
16    #[serde(flatten)]
17    pub namespaces: LinkedHashMap<String, Namespace>,
18}
19
20#[derive(Debug, Eq, PartialEq, Deserialize)]
21#[serde(untagged)]
22pub enum Namespace {
23    Map(LinkedHashMap<String, Namespace>),
24    DataType(DataType),
25}
26
27#[derive(Debug, Eq, PartialEq, Deserialize)]
28#[serde(untagged)]
29pub enum DataType {
30    Conditional(Box<Conditional>),
31    Numeric(Numeric),
32    Primitive(Primitive),
33    Structure(Box<Structure>),
34    Util(Box<Util>),
35    Custom(String),
36}
37
38#[derive(Debug, Eq, PartialEq)]
39pub enum Conditional {
40    Switch(Switch),
41    Option(DataType),
42}
43
44#[derive(Debug, Eq, PartialEq, Deserialize)]
45pub struct Switch {
46    name: Option<String>,
47    #[serde(rename = "compareTo")]
48    compare_to: String,
49    fields: LinkedHashMap<String, DataType>,
50    default: Option<DataType>,
51}
52
53#[derive(Debug, Eq, PartialEq)]
54pub enum Numeric {
55    Byte { signed: bool },
56    Short { signed: bool, byte_order: ByteOrder },
57    Int { signed: bool, byte_order: ByteOrder },
58    Long { signed: bool, byte_order: ByteOrder },
59    Float { byte_order: ByteOrder },
60    Double { byte_order: ByteOrder },
61    VarInt,
62}
63
64#[derive(Debug, Eq, PartialEq)]
65pub enum ByteOrder {
66    BigEndian,
67    LittleEndian,
68}
69
70#[derive(Debug, Eq, PartialEq, Deserialize)]
71#[serde(rename_all = "lowercase")]
72pub enum Primitive {
73    #[serde(rename = "bool")]
74    Boolean,
75    #[serde(rename = "cstring")]
76    String,
77    Void,
78}
79
80#[derive(Debug, Eq, PartialEq)]
81pub enum Structure {
82    /// Represents a list of values with same type.
83    Array(Array),
84    /// Represents a list of named values.
85    Container(Vec<Field>),
86    /// Represents a count field for an array or a buffer.
87    Count(Count),
88}
89
90#[derive(Debug, Eq, PartialEq, Deserialize)]
91pub struct Array {
92    /// The type of length prefix.
93    #[serde(rename = "countType")]
94    pub count_type: Option<DataType>,
95    /// A reference to the field counting the elements, or a fixed size.
96    pub count: Option<ArrayCount>,
97    /// The type of the elements.
98    #[serde(rename = "type")]
99    pub elements_type: DataType,
100}
101
102#[derive(Debug, Eq, PartialEq, Deserialize)]
103#[serde(untagged)]
104pub enum ArrayCount {
105    /// Reference to the field counting the elements.
106    FieldReference(String),
107    /// Array with fixed length.
108    FixedLength(u32),
109}
110
111#[derive(Debug, Eq, PartialEq, Deserialize)]
112pub struct Field {
113    pub name: Option<String>,
114    #[serde(rename = "type")]
115    pub field_type: DataType,
116    // Useless.
117    #[serde(rename = "anon")]
118    anonymous: Option<bool>,
119}
120
121#[derive(Debug, Eq, PartialEq, Deserialize)]
122pub struct Count {
123    /// The type of count.
124    #[serde(rename = "type")]
125    pub count_type: DataType,
126    /// A field to count for.
127    #[serde(rename = "countFor")]
128    pub count_for: String,
129}
130
131#[derive(Debug, Eq, PartialEq)]
132pub enum Util {
133    Buffer(Buffer),
134    Mapper(Mapper),
135    Bitfield(Vec<BitField>),
136    PrefixedString { count_type: DataType },
137    Loop(Box<Loop>),
138    TopBitSetTerminatedArray(Box<Structure>),
139}
140
141#[derive(Debug, Eq, PartialEq, Deserialize)]
142pub struct Buffer {
143    /// The type of length prefix.
144    #[serde(rename = "countType")]
145    pub count_type: Option<DataType>,
146    /// A reference to the field counting the elements, or a fixed size.
147    pub count: Option<ArrayCount>,
148    /// Represent rest bytes as-is.
149    pub rest: Option<bool>,
150}
151
152#[derive(Debug, Eq, PartialEq, Deserialize)]
153pub struct Mapper {
154    #[serde(rename = "type")]
155    pub mappings_type: String,
156    pub mappings: LinkedHashMap<String, String>,
157}
158
159#[derive(Debug, Deserialize, PartialEq, Eq)]
160pub struct BitField {
161    pub name: String,
162    pub size: usize,
163    pub signed: bool,
164}
165
166#[derive(Debug, Eq, PartialEq, Deserialize)]
167pub struct Loop {
168    #[serde(rename = "endVal")]
169    pub end_val: u32,
170    #[serde(rename = "type")]
171    pub data_type: DataType,
172}
173
174struct NumericVisitor;
175
176impl<'de> Visitor<'de> for NumericVisitor {
177    type Value = Numeric;
178
179    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
180        formatter.write_str("an valid numeric type string")
181    }
182
183    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
184    where
185        E: de::Error,
186    {
187        match value {
188            "i8" => Ok(Numeric::Byte { signed: true }),
189            "u8" => Ok(Numeric::Byte { signed: false }),
190            "i16" => Ok(Numeric::Short {
191                signed: true,
192                byte_order: ByteOrder::BigEndian,
193            }),
194            "u16" => Ok(Numeric::Short {
195                signed: false,
196                byte_order: ByteOrder::BigEndian,
197            }),
198            "li16" => Ok(Numeric::Short {
199                signed: true,
200                byte_order: ByteOrder::LittleEndian,
201            }),
202            "lu16" => Ok(Numeric::Short {
203                signed: false,
204                byte_order: ByteOrder::LittleEndian,
205            }),
206            "i32" => Ok(Numeric::Int {
207                signed: true,
208                byte_order: ByteOrder::BigEndian,
209            }),
210            "u32" => Ok(Numeric::Int {
211                signed: false,
212                byte_order: ByteOrder::BigEndian,
213            }),
214            "li32" => Ok(Numeric::Int {
215                signed: true,
216                byte_order: ByteOrder::LittleEndian,
217            }),
218            "lu32" => Ok(Numeric::Int {
219                signed: false,
220                byte_order: ByteOrder::LittleEndian,
221            }),
222            "i64" => Ok(Numeric::Long {
223                signed: true,
224                byte_order: ByteOrder::BigEndian,
225            }),
226            "u64" => Ok(Numeric::Long {
227                signed: false,
228                byte_order: ByteOrder::BigEndian,
229            }),
230            "li64" => Ok(Numeric::Long {
231                signed: true,
232                byte_order: ByteOrder::LittleEndian,
233            }),
234            "lu64" => Ok(Numeric::Long {
235                signed: false,
236                byte_order: ByteOrder::LittleEndian,
237            }),
238            "f32" => Ok(Numeric::Float {
239                byte_order: ByteOrder::BigEndian,
240            }),
241            "lf32" => Ok(Numeric::Float {
242                byte_order: ByteOrder::LittleEndian,
243            }),
244            "f64" => Ok(Numeric::Double {
245                byte_order: ByteOrder::BigEndian,
246            }),
247            "lf64" => Ok(Numeric::Double {
248                byte_order: ByteOrder::LittleEndian,
249            }),
250            "varint" => Ok(Numeric::VarInt),
251            _ => Err(de::Error::invalid_value(Unexpected::Str(&value), &self)),
252        }
253    }
254}
255
256impl<'de> Deserialize<'de> for Numeric {
257    fn deserialize<D>(deserializer: D) -> Result<Self, <D>::Error>
258    where
259        D: Deserializer<'de>,
260    {
261        deserializer.deserialize_str(NumericVisitor)
262    }
263}
264
265struct ConditionalVisitor;
266
267impl<'de> Visitor<'de> for ConditionalVisitor {
268    type Value = Conditional;
269
270    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
271        formatter.write_str("an valid `Conditional`")
272    }
273
274    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
275    where
276        A: SeqAccess<'de>,
277    {
278        let conditional_type: String = seq
279            .next_element()?
280            .ok_or_else(|| de::Error::invalid_length(0, &self))?;
281
282        match conditional_type.as_str() {
283            "switch" => {
284                let switch = seq
285                    .next_element()?
286                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
287
288                Ok(Conditional::Switch(switch))
289            }
290            "option" => {
291                let data_type = seq
292                    .next_element()?
293                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
294
295                Ok(Conditional::Option(data_type))
296            }
297            unknown_variant => {
298                // Attempt to find switch with wrong type.
299                let mut map: HashMap<String, String> = seq.next_element()?.ok_or_else(|| {
300                    de::Error::unknown_variant(unknown_variant, &["switch", "option"])
301                })?;
302
303                if map.len() == 1 {
304                    if let Some(compare_to) = map.remove("compareTo") {
305                        let switch = Switch {
306                            name: Some(unknown_variant.to_owned()),
307                            compare_to,
308                            fields: LinkedHashMap::new(),
309                            default: None,
310                        };
311
312                        return Ok(Conditional::Switch(switch));
313                    }
314                }
315
316                Err(de::Error::unknown_variant(
317                    unknown_variant,
318                    &["switch", "option"],
319                ))
320            }
321        }
322    }
323}
324
325impl<'de> Deserialize<'de> for Conditional {
326    fn deserialize<D>(deserializer: D) -> Result<Self, <D>::Error>
327    where
328        D: Deserializer<'de>,
329    {
330        deserializer.deserialize_seq(ConditionalVisitor)
331    }
332}
333
334struct StructureVisitor;
335
336impl<'de> Visitor<'de> for StructureVisitor {
337    type Value = Structure;
338
339    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
340        formatter.write_str("an valid `Structure`")
341    }
342
343    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
344    where
345        A: SeqAccess<'de>,
346    {
347        let struct_type: String = seq
348            .next_element()?
349            .ok_or_else(|| de::Error::invalid_length(0, &self))?;
350
351        match struct_type.as_str() {
352            "container" => {
353                let fields = seq
354                    .next_element()?
355                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
356
357                Ok(Structure::Container(fields))
358            }
359            "array" => {
360                let array = seq
361                    .next_element()?
362                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
363
364                Ok(Structure::Array(array))
365            }
366            "count" => {
367                let count = seq
368                    .next_element()?
369                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
370
371                Ok(Structure::Count(count))
372            }
373            unknown_variant => Err(de::Error::unknown_variant(
374                unknown_variant,
375                &["container", "array", "count"],
376            )),
377        }
378    }
379}
380
381impl<'de> Deserialize<'de> for Structure {
382    fn deserialize<D>(deserializer: D) -> Result<Self, <D>::Error>
383    where
384        D: Deserializer<'de>,
385    {
386        deserializer.deserialize_seq(StructureVisitor)
387    }
388}
389
390struct UtilVisitor;
391
392impl<'de> Visitor<'de> for UtilVisitor {
393    type Value = Util;
394
395    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
396        formatter.write_str("an valid util")
397    }
398
399    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, <A as SeqAccess<'de>>::Error>
400    where
401        A: SeqAccess<'de>,
402    {
403        let util_type: String = seq
404            .next_element()?
405            .ok_or_else(|| de::Error::invalid_length(0, &self))?;
406
407        match util_type.as_str() {
408            "buffer" => {
409                let buffer = seq
410                    .next_element()?
411                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
412
413                Ok(Util::Buffer(buffer))
414            }
415            "mapper" => {
416                let mapper = seq
417                    .next_element()?
418                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
419
420                Ok(Util::Mapper(mapper))
421            }
422            "bitfield" => {
423                let bitfields = seq
424                    .next_element()?
425                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
426
427                Ok(Util::Bitfield(bitfields))
428            }
429            "pstring" => {
430                let mut map: HashMap<String, DataType> = seq
431                    .next_element()?
432                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
433
434                let count_type = map
435                    .remove("countType")
436                    .ok_or_else(|| de::Error::missing_field("countType"))?;
437
438                Ok(Util::PrefixedString { count_type })
439            }
440            "topBitSetTerminatedArray" => {
441                let mut value: HashMap<String, Structure> = seq
442                    .next_element()?
443                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
444
445                let structure = value
446                    .remove("type")
447                    .ok_or_else(|| de::Error::missing_field("type"))?;
448
449                Ok(Util::TopBitSetTerminatedArray(Box::new(structure)))
450            }
451            unknown_variant => {
452                // This is what happens when the nodejs developers write a "cool" spec.
453                let loop_util: Loop = seq.next_element()?.ok_or_else(|| {
454                    de::Error::unknown_variant(
455                        unknown_variant,
456                        &["buffer", "mapper", "bitfield", "pstring"],
457                    )
458                })?;
459
460                Ok(Util::Loop(Box::new(loop_util)))
461            }
462        }
463    }
464}
465
466impl<'de> Deserialize<'de> for Util {
467    fn deserialize<D>(deserializer: D) -> Result<Self, <D>::Error>
468    where
469        D: Deserializer<'de>,
470    {
471        deserializer.deserialize_seq(UtilVisitor)
472    }
473}
474
475#[cfg(test)]
476mod tests {
477    use crate::*;
478    use serde_test::{assert_de_tokens, Token};
479    use std::fs;
480    use std::fs::File;
481
482    #[test]
483    fn test_decode_protocols_data() {
484        let paths = fs::read_dir("test").expect("Failed to open test folder");
485
486        for entry_res in paths.into_iter() {
487            let entry = entry_res.expect("Failed to get test folder entry");
488            let file = File::open(entry.path()).expect("Failed to read file");
489
490            let name = entry
491                .file_name()
492                .into_string()
493                .expect("Failed to get entry name");
494
495            read_protocol(&file).expect(&format!("Failed to read \"{}\" protocol", name));
496        }
497    }
498
499    #[test]
500    fn test_decode_i8() {
501        assert_de_tokens(&Numeric::Byte { signed: true }, &[Token::String("i8")]);
502    }
503
504    #[test]
505    fn test_decode_u8() {
506        assert_de_tokens(&Numeric::Byte { signed: false }, &[Token::String("u8")]);
507    }
508
509    #[test]
510    fn test_decode_i16() {
511        assert_de_tokens(
512            &Numeric::Short {
513                signed: true,
514                byte_order: ByteOrder::BigEndian,
515            },
516            &[Token::String("i16")],
517        );
518    }
519
520    #[test]
521    fn test_decode_u16() {
522        assert_de_tokens(
523            &Numeric::Short {
524                signed: false,
525                byte_order: ByteOrder::BigEndian,
526            },
527            &[Token::String("u16")],
528        );
529    }
530
531    #[test]
532    fn test_decode_li16() {
533        assert_de_tokens(
534            &Numeric::Short {
535                signed: true,
536                byte_order: ByteOrder::LittleEndian,
537            },
538            &[Token::String("li16")],
539        );
540    }
541
542    #[test]
543    fn test_decode_lu16() {
544        assert_de_tokens(
545            &Numeric::Short {
546                signed: false,
547                byte_order: ByteOrder::LittleEndian,
548            },
549            &[Token::String("lu16")],
550        );
551    }
552
553    #[test]
554    fn test_decode_i32() {
555        assert_de_tokens(
556            &Numeric::Int {
557                signed: true,
558                byte_order: ByteOrder::BigEndian,
559            },
560            &[Token::String("i32")],
561        );
562    }
563
564    #[test]
565    fn test_decode_u32() {
566        assert_de_tokens(
567            &Numeric::Int {
568                signed: false,
569                byte_order: ByteOrder::BigEndian,
570            },
571            &[Token::String("u32")],
572        );
573    }
574
575    #[test]
576    fn test_decode_li32() {
577        assert_de_tokens(
578            &Numeric::Int {
579                signed: true,
580                byte_order: ByteOrder::LittleEndian,
581            },
582            &[Token::String("li32")],
583        );
584    }
585
586    #[test]
587    fn test_decode_lu32() {
588        assert_de_tokens(
589            &Numeric::Int {
590                signed: false,
591                byte_order: ByteOrder::LittleEndian,
592            },
593            &[Token::String("lu32")],
594        );
595    }
596
597    #[test]
598    fn test_decode_i64() {
599        assert_de_tokens(
600            &Numeric::Long {
601                signed: true,
602                byte_order: ByteOrder::BigEndian,
603            },
604            &[Token::String("i64")],
605        );
606    }
607
608    #[test]
609    fn test_decode_u64() {
610        assert_de_tokens(
611            &Numeric::Long {
612                signed: false,
613                byte_order: ByteOrder::BigEndian,
614            },
615            &[Token::String("u64")],
616        );
617    }
618
619    #[test]
620    fn test_decode_li64() {
621        assert_de_tokens(
622            &Numeric::Long {
623                signed: true,
624                byte_order: ByteOrder::LittleEndian,
625            },
626            &[Token::String("li64")],
627        );
628    }
629
630    #[test]
631    fn test_decode_lu64() {
632        assert_de_tokens(
633            &Numeric::Long {
634                signed: false,
635                byte_order: ByteOrder::LittleEndian,
636            },
637            &[Token::String("lu64")],
638        );
639    }
640
641    #[test]
642    fn test_decode_f32() {
643        assert_de_tokens(
644            &Numeric::Float {
645                byte_order: ByteOrder::BigEndian,
646            },
647            &[Token::String("f32")],
648        );
649    }
650
651    #[test]
652    fn test_decode_lf32() {
653        assert_de_tokens(
654            &Numeric::Float {
655                byte_order: ByteOrder::LittleEndian,
656            },
657            &[Token::String("lf32")],
658        );
659    }
660
661    #[test]
662    fn test_decode_f64_numeric() {
663        assert_de_tokens(
664            &Numeric::Double {
665                byte_order: ByteOrder::BigEndian,
666            },
667            &[Token::String("f64")],
668        );
669    }
670
671    #[test]
672    fn test_decode_lf64_numeric() {
673        assert_de_tokens(
674            &Numeric::Double {
675                byte_order: ByteOrder::LittleEndian,
676            },
677            &[Token::String("lf64")],
678        );
679    }
680
681    #[test]
682    fn test_decode_boolean() {
683        assert_de_tokens(
684            &Primitive::Boolean,
685            &[
686                Token::Enum { name: "Primitive" },
687                Token::String("bool"),
688                Token::Unit,
689            ],
690        );
691    }
692
693    #[test]
694    fn test_decode_string() {
695        assert_de_tokens(
696            &Primitive::String,
697            &[
698                Token::Enum { name: "Primitive" },
699                Token::String("cstring"),
700                Token::Unit,
701            ],
702        );
703    }
704
705    #[test]
706    fn test_decode_void() {
707        assert_de_tokens(
708            &Primitive::Void,
709            &[
710                Token::Enum { name: "Primitive" },
711                Token::String("void"),
712                Token::Unit,
713            ],
714        );
715    }
716
717    #[test]
718    fn test_decode_numeric_data_type() {
719        assert_de_tokens(
720            &DataType::Numeric(Numeric::Float {
721                byte_order: ByteOrder::BigEndian,
722            }),
723            &[Token::String("f32")],
724        );
725    }
726
727    #[test]
728    fn test_decode_primitive_data_type() {
729        assert_de_tokens(
730            &DataType::Primitive(Primitive::Boolean),
731            &[Token::String("bool")],
732        );
733    }
734
735    #[test]
736    fn test_decode_container_data_type() {
737        let fields = vec![Field {
738            name: Some("serverPort".to_string()),
739            field_type: DataType::Numeric(Numeric::Short {
740                signed: false,
741                byte_order: ByteOrder::BigEndian,
742            }),
743            anonymous: None,
744        }];
745
746        let container = Structure::Container(fields);
747
748        assert_de_tokens(
749            &container,
750            &[
751                Token::Seq { len: Some(2) },
752                Token::String("container"),
753                Token::Seq { len: Some(1) },
754                Token::Struct {
755                    name: "Field",
756                    len: 2,
757                },
758                Token::Str("name"),
759                Token::Some,
760                Token::String("serverPort"),
761                Token::Str("type"),
762                Token::String("u16"),
763                Token::StructEnd,
764                Token::SeqEnd,
765                Token::SeqEnd,
766            ],
767        );
768    }
769
770    #[test]
771    fn test_decode_container_with_container_data_type() {
772        let inner_container_fields = vec![Field {
773            name: Some("name".to_string()),
774            field_type: DataType::Numeric(Numeric::VarInt),
775            anonymous: None,
776        }];
777
778        let fields = vec![Field {
779            name: Some("inner_container".to_string()),
780            field_type: DataType::Structure(Box::new(Structure::Container(inner_container_fields))),
781            anonymous: None,
782        }];
783
784        let container = Structure::Container(fields);
785
786        assert_de_tokens(
787            &container,
788            &[
789                Token::Seq { len: Some(2) },
790                Token::String("container"),
791                Token::Seq { len: Some(1) },
792                Token::Struct {
793                    name: "Field",
794                    len: 2,
795                },
796                Token::Str("name"),
797                Token::Some,
798                Token::String("inner_container"),
799                Token::Str("type"),
800                Token::Seq { len: Some(2) },
801                Token::String("container"),
802                Token::Seq { len: Some(1) },
803                Token::Struct {
804                    name: "Field",
805                    len: 2,
806                },
807                Token::Str("name"),
808                Token::String("name"),
809                Token::Str("type"),
810                Token::String("varint"),
811                Token::StructEnd,
812                Token::SeqEnd,
813                Token::SeqEnd,
814                Token::StructEnd,
815                Token::SeqEnd,
816                Token::SeqEnd,
817            ],
818        );
819    }
820
821    #[test]
822    fn test_decode_array_data_type() {
823        let array = Structure::Array(Array {
824            count_type: Some(DataType::Numeric(Numeric::VarInt)),
825            count: None,
826            elements_type: DataType::Primitive(Primitive::String),
827        });
828
829        assert_de_tokens(
830            &array,
831            &[
832                Token::Seq { len: Some(2) },
833                Token::String("array"),
834                Token::Struct {
835                    name: "Array",
836                    len: 2,
837                },
838                Token::Str("countType"),
839                Token::Some,
840                Token::String("varint"),
841                Token::Str("type"),
842                Token::String("cstring"),
843                Token::StructEnd,
844                Token::SeqEnd,
845            ],
846        );
847    }
848
849    #[test]
850    fn test_decode_array_with_container_data_type() {
851        let fields = vec![Field {
852            name: Some("name".to_string()),
853            field_type: DataType::Numeric(Numeric::VarInt),
854            anonymous: None,
855        }];
856
857        let array = Structure::Array(Array {
858            count_type: Some(DataType::Numeric(Numeric::VarInt)),
859            count: None,
860            elements_type: DataType::Structure(Box::new(Structure::Container(fields))),
861        });
862
863        assert_de_tokens(
864            &array,
865            &[
866                Token::Seq { len: Some(2) },
867                Token::String("array"),
868                Token::Struct {
869                    name: "Array",
870                    len: 2,
871                },
872                Token::Str("countType"),
873                Token::Some,
874                Token::String("varint"),
875                Token::Str("type"),
876                Token::Seq { len: Some(2) },
877                Token::String("container"),
878                Token::Seq { len: Some(1) },
879                Token::Struct {
880                    name: "Field",
881                    len: 2,
882                },
883                Token::Str("name"),
884                Token::String("name"),
885                Token::Str("type"),
886                Token::String("varint"),
887                Token::StructEnd,
888                Token::SeqEnd,
889                Token::SeqEnd,
890                Token::StructEnd,
891                Token::SeqEnd,
892            ],
893        );
894    }
895
896    #[test]
897    fn test_decode_count_data_type() {
898        let count = Structure::Count(Count {
899            count_type: DataType::Numeric(Numeric::VarInt),
900            count_for: "test".to_string(),
901        });
902
903        assert_de_tokens(
904            &count,
905            &[
906                Token::Seq { len: Some(2) },
907                Token::String("count"),
908                Token::Struct {
909                    name: "Count",
910                    len: 2,
911                },
912                Token::Str("type"),
913                Token::String("varint"),
914                Token::Str("countFor"),
915                Token::String("test"),
916                Token::StructEnd,
917                Token::SeqEnd,
918            ],
919        );
920    }
921
922    #[test]
923    fn test_decode_array_ref_field() {
924        let array = Structure::Array(Array {
925            count_type: None,
926            count: Some(ArrayCount::FieldReference("field".to_string())),
927            elements_type: DataType::Primitive(Primitive::String),
928        });
929
930        assert_de_tokens(
931            &array,
932            &[
933                Token::Seq { len: Some(2) },
934                Token::String("array"),
935                Token::Struct {
936                    name: "Array",
937                    len: 2,
938                },
939                Token::Str("count"),
940                Token::Some,
941                Token::String("field"),
942                Token::Str("type"),
943                Token::String("cstring"),
944                Token::StructEnd,
945                Token::SeqEnd,
946            ],
947        );
948    }
949
950    #[test]
951    fn test_decode_array_fixed_length() {
952        let array = Structure::Array(Array {
953            count_type: None,
954            count: Some(ArrayCount::FixedLength(4)),
955            elements_type: DataType::Primitive(Primitive::String),
956        });
957
958        assert_de_tokens(
959            &array,
960            &[
961                Token::Seq { len: Some(2) },
962                Token::String("array"),
963                Token::Struct {
964                    name: "Array",
965                    len: 2,
966                },
967                Token::Str("count"),
968                Token::Some,
969                Token::I32(4),
970                Token::Str("type"),
971                Token::String("cstring"),
972                Token::StructEnd,
973                Token::SeqEnd,
974            ],
975        );
976    }
977
978    #[test]
979    fn test_decode_prefixed_string() {
980        let util = Util::PrefixedString {
981            count_type: DataType::Numeric(Numeric::VarInt),
982        };
983
984        assert_de_tokens(
985            &util,
986            &[
987                Token::Seq { len: Some(2) },
988                Token::Str("pstring"),
989                Token::Struct { name: "", len: 1 },
990                Token::Str("countType"),
991                Token::String("varint"),
992                Token::StructEnd,
993                Token::SeqEnd,
994            ],
995        );
996    }
997
998    #[test]
999    fn test_decode_buffer() {
1000        let util = Util::Buffer(Buffer {
1001            count_type: Some(DataType::Numeric(Numeric::Int {
1002                signed: true,
1003                byte_order: ByteOrder::BigEndian,
1004            })),
1005            count: None,
1006            rest: None,
1007        });
1008
1009        assert_de_tokens(
1010            &util,
1011            &[
1012                Token::Seq { len: Some(2) },
1013                Token::String("buffer"),
1014                Token::Struct {
1015                    name: "Buffer",
1016                    len: 1,
1017                },
1018                Token::String("countType"),
1019                Token::Some,
1020                Token::String("i32"),
1021                Token::StructEnd,
1022                Token::SeqEnd,
1023            ],
1024        );
1025    }
1026
1027    #[test]
1028    fn test_decode_option() {
1029        let conditional = Conditional::Option(DataType::Numeric(Numeric::Byte { signed: false }));
1030
1031        assert_de_tokens(
1032            &conditional,
1033            &[
1034                Token::Seq { len: Some(2) },
1035                Token::String("option"),
1036                Token::String("u8"),
1037                Token::SeqEnd,
1038            ],
1039        );
1040    }
1041
1042    #[test]
1043    fn test_decode_bad_switch() {
1044        let conditional = Conditional::Switch(Switch {
1045            name: Some("particleData".to_string()),
1046            compare_to: "particleId".to_string(),
1047            fields: Default::default(),
1048            default: None,
1049        });
1050
1051        assert_de_tokens(
1052            &conditional,
1053            &[
1054                Token::Seq { len: Some(2) },
1055                Token::String("particleData"),
1056                Token::Struct { name: "", len: 1 },
1057                Token::String("compareTo"),
1058                Token::String("particleId"),
1059                Token::StructEnd,
1060                Token::SeqEnd,
1061            ],
1062        );
1063    }
1064}