diff --git a/nbt/snbt_decode.go b/nbt/snbt_decode.go index 1185864..9495812 100644 --- a/nbt/snbt_decode.go +++ b/nbt/snbt_decode.go @@ -1,9 +1,5 @@ package nbt -import ( - "fmt" -) - type decodeState struct { data []byte off int // next read offset in data @@ -16,28 +12,27 @@ const phasePanicMsg = "SNBT decoder out of sync - data changing underfoot?" func (e *Encoder) WriteSNBT(snbt string) error { d := decodeState{data: []byte(snbt)} d.scan.reset() + return writeValue(e, &d, "") +} + +func writeValue(e *Encoder, d *decodeState, tagName string) error { d.scanWhile(scanSkipSpace) switch d.opcode { default: panic(phasePanicMsg) - case scanBeginLiteral: - return writeLiteral(e, &d) + return writeLiteral(e, d, tagName) case scanBeginCompound: - panic("not implemented") - + return writeCompound(e, d, tagName) case scanBeginList: panic("not implemented") } - return nil } -func writeLiteral(e *Encoder, d *decodeState) error { +func writeLiteral(e *Encoder, d *decodeState, tagName string) error { start := d.readIndex() - d.scanNext() d.scanWhile(scanContinue) literal := d.data[start:d.readIndex()] - fmt.Printf("%d %d [%d]- %q\n", start, d.off, d.opcode, literal) switch literal[0] { case '"', '\'': // TAG_String @@ -52,8 +47,42 @@ func writeLiteral(e *Encoder, d *decodeState) error { return nil } -func writeCompound(e *Encoder, d *decodeState) error { - e.writeTag(TagCompound, "") +func writeCompound(e *Encoder, d *decodeState, tagName string) error { + e.writeTag(TagCompound, tagName) + for { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndValue { + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + // read tag name + start := d.readIndex() + d.scanWhile(scanContinue) + tagName := string(d.data[start:d.readIndex()]) + // read value + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanCompoundTagName { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + writeLiteral(e, d, tagName) + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndValue { + break + } + if d.opcode != scanCompoundValue { + panic(phasePanicMsg) + } + } + e.w.Write([]byte{TagEnd}) return nil } diff --git a/nbt/snbt_decode_test.go b/nbt/snbt_decode_test.go index 144a418..f6a43ec 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(`"12345"`); err != nil { + if err := e.WriteSNBT(`{ abc: a123}`); err != nil { t.Fatal(err) } t.Log(buf.Bytes()) diff --git a/nbt/snbt_scanner.go b/nbt/snbt_scanner.go index e47ddf9..49cc566 100644 --- a/nbt/snbt_scanner.go +++ b/nbt/snbt_scanner.go @@ -397,6 +397,7 @@ func (s *scanner) stateEndValue(c byte) int { } return s.error(c, "") } + func (s *scanner) error(c byte, context string) int { s.step = s.stateError s.err = errors.New(context) diff --git a/nbt/snbt_scanner_test.go b/nbt/snbt_scanner_test.go index 029288a..83b4c9d 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(`1234`) { + for _, c := range []byte(`{ "a b\"c": {}, def: 12345, 'gh"i': 0.123f}`) { t.Logf("[%c] - %d", c, s.step(c)) } t.Logf("[%c] - %d", ' ', s.eof())