From 233b44a13f675bc201cf15964aa2e2cfe2c18a2f Mon Sep 17 00:00:00 2001 From: Tnze Date: Wed, 26 May 2021 15:02:49 +0800 Subject: [PATCH] Basic SNBT list support --- nbt/snbt_decode.go | 50 +++++++++++++++++++++++++++++++++++++++- nbt/snbt_decode_test.go | 2 +- nbt/snbt_scanner.go | 2 +- nbt/snbt_scanner_test.go | 4 ++-- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/nbt/snbt_decode.go b/nbt/snbt_decode.go index 418e391..f450ff8 100644 --- a/nbt/snbt_decode.go +++ b/nbt/snbt_decode.go @@ -1,6 +1,7 @@ package nbt import ( + "bytes" "math" "strconv" "strings" @@ -31,7 +32,7 @@ func writeValue(e *Encoder, d *decodeState, tagName string) error { case scanBeginCompound: return writeCompound(e, d, tagName) case scanBeginList: - panic("not implemented") + return writeListOrArray(e, d, tagName) } } @@ -105,6 +106,53 @@ func writeCompound(e *Encoder, d *decodeState, tagName string) error { return nil } +func writeListOrArray(e *Encoder, d *decodeState, tagName string) error { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndValue { // ']', empty TAG_List + e.writeTag(TagList, tagName) + e.writeInt32(0) + return nil + } + + start := d.readIndex() + + switch d.opcode { + case scanBeginLiteral: + d.scanWhile(scanContinue) + literal := d.data[start:d.readIndex()] + if d.opcode == scanListType { // TAG_X_Array + //listType := literal[0] + break + } + if d.opcode != scanListValue { // TAG_List + panic(phasePanicMsg) + } + // TODO + parseLiteral(literal) + fallthrough + case scanBeginList: // TAG_List + // We don't know the length of the List, + // so we read them into a buffer and count. + var buf bytes.Buffer + e2 := NewEncoder(&buf) + var count int + for { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndValue { + break + } + if d.opcode == scanListValue { + // TODO + e2.writeInt32(0) + } + } + e.writeListHeader(TagList, tagName, count) + e.w.Write(buf.Bytes()) + case scanBeginCompound: // TAG_List + } + return nil +} + // readIndex returns the position of the last byte read. func (d *decodeState) readIndex() int { return d.off - 1 diff --git a/nbt/snbt_decode_test.go b/nbt/snbt_decode_test.go index 2053d80..54e9e54 100644 --- a/nbt/snbt_decode_test.go +++ b/nbt/snbt_decode_test.go @@ -8,7 +8,7 @@ import ( func TestEncoder_WriteSNBT(t *testing.T) { var buf bytes.Buffer e := NewEncoder(&buf) - if err := e.WriteSNBT(`{ abc: 123F, def: {}}`); err != nil { + if err := e.WriteSNBT(`[1,2,3]`); err != nil { t.Fatal(err) } t.Log(buf.Bytes()) diff --git a/nbt/snbt_scanner.go b/nbt/snbt_scanner.go index 49cc566..d97e8d2 100644 --- a/nbt/snbt_scanner.go +++ b/nbt/snbt_scanner.go @@ -239,7 +239,7 @@ func (s *scanner) stateListOrArray(c byte) int { switch c { case 'B', 'I', 'L': s.step = s.stateListOrArrayT - return scanContinue + return scanBeginLiteral case ']': return s.stateEndValue(c) default: diff --git a/nbt/snbt_scanner_test.go b/nbt/snbt_scanner_test.go index 83b4c9d..5810724 100644 --- a/nbt/snbt_scanner_test.go +++ b/nbt/snbt_scanner_test.go @@ -6,10 +6,10 @@ import ( ) func TestSNBT_checkScanCode(t *testing.T) { - t.SkipNow() + //t.SkipNow() var s scanner s.reset() - for _, c := range []byte(`{ "a b\"c": {}, def: 12345, 'gh"i': 0.123f}`) { + for _, c := range []byte(`[I;1,2,3]`) { t.Logf("[%c] - %d", c, s.step(c)) } t.Logf("[%c] - %d", ' ', s.eof())