Basic SNBT list support

This commit is contained in:
Tnze
2021-05-26 15:02:49 +08:00
parent e2fbef9bea
commit 233b44a13f
4 changed files with 53 additions and 5 deletions

View File

@ -1,6 +1,7 @@
package nbt package nbt
import ( import (
"bytes"
"math" "math"
"strconv" "strconv"
"strings" "strings"
@ -31,7 +32,7 @@ func writeValue(e *Encoder, d *decodeState, tagName string) error {
case scanBeginCompound: case scanBeginCompound:
return writeCompound(e, d, tagName) return writeCompound(e, d, tagName)
case scanBeginList: 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 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<TAG_String>
panic(phasePanicMsg)
}
// TODO
parseLiteral(literal)
fallthrough
case scanBeginList: // TAG_List<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<TAG_Compound>
}
return nil
}
// readIndex returns the position of the last byte read. // readIndex returns the position of the last byte read.
func (d *decodeState) readIndex() int { func (d *decodeState) readIndex() int {
return d.off - 1 return d.off - 1

View File

@ -8,7 +8,7 @@ import (
func TestEncoder_WriteSNBT(t *testing.T) { func TestEncoder_WriteSNBT(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
e := NewEncoder(&buf) 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.Fatal(err)
} }
t.Log(buf.Bytes()) t.Log(buf.Bytes())

View File

@ -239,7 +239,7 @@ func (s *scanner) stateListOrArray(c byte) int {
switch c { switch c {
case 'B', 'I', 'L': case 'B', 'I', 'L':
s.step = s.stateListOrArrayT s.step = s.stateListOrArrayT
return scanContinue return scanBeginLiteral
case ']': case ']':
return s.stateEndValue(c) return s.stateEndValue(c)
default: default:

View File

@ -6,10 +6,10 @@ import (
) )
func TestSNBT_checkScanCode(t *testing.T) { func TestSNBT_checkScanCode(t *testing.T) {
t.SkipNow() //t.SkipNow()
var s scanner var s scanner
s.reset() 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", c, s.step(c))
} }
t.Logf("[%c] - %d", ' ', s.eof()) t.Logf("[%c] - %d", ' ', s.eof())