@@ -211,12 +211,14 @@ mod test {
211211 use std:: io:: Cursor ;
212212
213213 use crate :: Error ;
214+ use crate :: compound:: NbtCompound ;
214215 use crate :: deserializer:: from_bytes;
215216 use crate :: nbt_byte_array;
216217 use crate :: nbt_int_array;
217218 use crate :: nbt_long_array;
218- use crate :: serializer:: to_bytes;
219219 use crate :: serializer:: to_bytes_named;
220+ use crate :: serializer:: { WriteAdaptor , to_bytes} ;
221+ use crate :: tag:: NbtTag ;
220222 use crate :: { deserializer:: from_bytes_unnamed, serializer:: to_bytes_unnamed} ;
221223 use serde:: { Deserialize , Serialize } ;
222224
@@ -406,6 +408,88 @@ mod test {
406408 assert_eq ! ( list_compound, recreated_struct) ;
407409 }
408410
411+ #[ test]
412+ fn wrapper_compound_lists ( ) {
413+ let mut vec: Vec < NbtTag > = Vec :: new ( ) ;
414+
415+ // These tags will be wrapped during serialization.
416+ vec. push ( NbtTag :: Int ( -1823 ) ) ;
417+ vec. push ( NbtTag :: Int ( 123 ) ) ;
418+ vec. push ( NbtTag :: String ( "Not an int" . to_string ( ) ) ) ;
419+ vec. push ( NbtTag :: Byte ( 2 ) ) ;
420+
421+ // This compound will not, since the list is already a list of compound tags.
422+ // This compound cannot be unwrapped in any way, so it is preserved
423+ // on deserialization.
424+ vec. push ( NbtTag :: Compound ( {
425+ let mut compound = NbtCompound :: new ( ) ;
426+ compound. put_short ( "example" , 1234 ) ;
427+ compound
428+ } ) ) ;
429+
430+ // This wrapper compound will be wrapped because we want to preserve the
431+ // original data during deserialization.
432+ //
433+ // Suppose we had {"": `tag`}. If we didn't wrap this, on deserialization,
434+ // we would get `tag`, which doesn't match the serialized compound tag.
435+ // Therefore, we must wrap it and serialize {"": {"": `tag`}}.
436+ // Then on deserialization, we get {"": `tag`}, which matches what we wanted
437+ // to serialize in the first place.
438+ //
439+ // This compound represents {"": 1L}.
440+ vec. push ( NbtTag :: Compound ( {
441+ let mut compound = NbtCompound :: new ( ) ;
442+ compound. put_long ( "" , 1 ) ;
443+ compound
444+ } ) ) ;
445+
446+ let expected_bytes = [
447+ 0x09 , // List type
448+ 0x0A , // This list is a compound tag list
449+ 0x00 , 0x00 , 0x00 , 0x06 , // This list has 6 elements.
450+ // Now for parsing each compound tag:
451+ 0x03 , // Int type
452+ 0x00 , 0x00 , // Empty key
453+ 0xFF , 0xFF , 0xF8 , 0xE1 , // -1823
454+ 0x00 , // End
455+ 0x03 , // Int type
456+ 0x00 , 0x00 , // Empty key
457+ 0x00 , 0x00 , 0x00 , 0x7B , // 123
458+ 0x00 , // End
459+ 0x08 , // String type
460+ 0x00 , 0x00 , // Empty key
461+ 0x00 , 0x0A , // The string is 10 characters long.
462+ 0x4E , 0x6F , 0x74 , 0x20 , 0x61 , 0x6E , 0x20 , 0x69 , 0x6E , 0x74 , // "Not an int"
463+ 0x00 , // End
464+ 0x01 , // Byte type
465+ 0x00 , 0x00 , // Empty key
466+ 0x02 , // 2b
467+ 0x00 , // End
468+ // For the first (unwrapped) compound:
469+ 0x02 , // Short type
470+ 0x00 , 0x07 , // The key is 7 characters long.
471+ 0x65 , 0x78 , 0x61 , 0x6D , 0x70 , 0x6C , 0x65 , // "example"
472+ 0x04 , 0xD2 , // 1234
473+ 0x00 , // End
474+ // For the second (wrapped) wrapper compound:
475+ 0x0A , // Compound type
476+ 0x00 , 0x00 , // Empty key
477+ 0x04 , // Long type
478+ 0x00 , 0x00 , // Empty key
479+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , // 1L
480+ 0x00 , // End
481+ 0x00 , // End
482+ ] ;
483+
484+ let mut bytes = Vec :: new ( ) ;
485+ let mut write_adaptor = WriteAdaptor :: new ( & mut bytes) ;
486+ NbtTag :: List ( vec)
487+ . serialize ( & mut write_adaptor)
488+ . expect ( "Expected serialization to succeed" ) ;
489+
490+ assert_eq ! ( bytes, expected_bytes) ;
491+ }
492+
409493 #[ test]
410494 fn nbt_arrays ( ) {
411495 #[ derive( Serialize ) ]
0 commit comments