From dd1b8fd9c96c5df276978e772c3579a9fa706fff Mon Sep 17 00:00:00 2001 From: Tnze Date: Thu, 27 May 2021 01:33:08 +0800 Subject: [PATCH] Support TAG_Byte_Array, TAG_Int_Array and TAG_Long_Array --- nbt/snbt_decode.go | 46 +++++++++++++++++++++++++++++++++++++++- nbt/snbt_scanner.go | 9 +++++++- nbt/snbt_scanner_test.go | 1 + 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/nbt/snbt_decode.go b/nbt/snbt_decode.go index 1b26706..0ffa2c8 100644 --- a/nbt/snbt_decode.go +++ b/nbt/snbt_decode.go @@ -121,7 +121,49 @@ func writeListOrArray(e *Encoder, d *decodeState, tagName string) error { d.scanWhile(scanContinue) literal := d.data[start:d.readIndex()] if d.opcode == scanListType { // TAG_X_Array - //listType := literal[0] + var elemType byte + switch literal[0] { + case 'B': + e.writeTag(TagByteArray, tagName) + elemType = TagByte + case 'I': + e.writeTag(TagIntArray, tagName) + elemType = TagInt + case 'L': + e.writeTag(TagLongArray, tagName) + elemType = TagLong + } + for { + d.scanNext() + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndValue { // ] + break + } + if d.opcode != scanBeginLiteral { + return errors.New("not literal in Array") + } + start := d.readIndex() + + d.scanWhile(scanContinue) + literal := d.data[start:d.readIndex()] + tagType, litVal := parseLiteral(literal) + if tagType != elemType { + return errors.New("unexpected element type in TAG_Array") + } + switch elemType { + case TagByte: + e2.w.Write([]byte{byte(litVal.(int8))}) + case TagInt: + e2.writeInt32(litVal.(int32)) + case TagLong: + e2.writeInt64(litVal.(int64)) + } + count++ + } + e.writeInt32(int32(count)) + e.w.Write(buf.Bytes()) break } if d.opcode != scanListValue { // TAG_List @@ -157,6 +199,8 @@ func writeListOrArray(e *Encoder, d *decodeState, tagName string) error { e.writeListHeader(tagType, tagName, count) e.w.Write(buf.Bytes()) case scanBeginList: // TAG_List + e.writeListHeader(TagList, tagName, count) + e.w.Write(buf.Bytes()) case scanBeginCompound: // TAG_List for { if d.opcode == scanSkipSpace { diff --git a/nbt/snbt_scanner.go b/nbt/snbt_scanner.go index d97e8d2..44c043f 100644 --- a/nbt/snbt_scanner.go +++ b/nbt/snbt_scanner.go @@ -249,12 +249,19 @@ func (s *scanner) stateListOrArray(c byte) int { func (s *scanner) stateListOrArrayT(c byte) int { if c == ';' { - s.step = s.stateBeginValue + s.step = s.stateArrayT return scanListType } return s.stateInUnquotedString(c) } +func (s *scanner) stateArrayT(c byte) int { + if c == ']' { // empty array + return scanEndValue + } + return s.stateBeginValue(c) +} + func (s *scanner) stateNeg(c byte) int { if isNumber(c) { s.step = s.stateNum0 diff --git a/nbt/snbt_scanner_test.go b/nbt/snbt_scanner_test.go index ddbb675..cf5de10 100644 --- a/nbt/snbt_scanner_test.go +++ b/nbt/snbt_scanner_test.go @@ -67,6 +67,7 @@ func TestSNBT_list(t *testing.T) { `[{}, {}, {"a\"b":520}]`, // List of Compound `[B,C,D]`, `[L, "abc"]`, // List of string (like array) `[B; 01B, 02B, 3B, 10B, 127B]`, // Array + `[I;]`, // Empty array } var s scanner scan := func(str string) bool {