diff --git a/tape/dynamic.go b/tape/dynamic.go index e56da67..ae2981c 100644 --- a/tape/dynamic.go +++ b/tape/dynamic.go @@ -6,6 +6,8 @@ package tape // TODO: add support for struct tags: `tape:"0000"`, tape:"0001"` so they can get // transformed into tables with a defined schema +// TODO: test all of these smaller functions individually + import "fmt" import "reflect" @@ -346,10 +348,12 @@ func peekSlice(decoder *Decoder, tag Tag) (Tag, int, error) { for { elem, populated, n, err := peekSliceOnce(decoder, tag, offset) if err != nil { return 0, 0, err } - offset += n + offset = n dimension += 1 if elem.Is(OTA) { if !populated { + // default to a large byte array, will be + // interpreted as a string. return LBA, dimension + 1, nil } } else { @@ -371,7 +375,7 @@ func peekSliceOnce(decoder *Decoder, tag Tag, offset int) (elem Tag, populated b headerBytes, err := decoder.Peek(elemTagEnd) if err != nil { return 0, false, 0, err } - elem = Tag(headerBytes[len(headerBytes)]) + elem = Tag(headerBytes[len(headerBytes) - 1]) for index := lengthStart; index < lengthEnd; index += 1 { if headerBytes[index] > 0 { populated = true diff --git a/tape/dynamic_test.go b/tape/dynamic_test.go index 274bf46..fbbea68 100644 --- a/tape/dynamic_test.go +++ b/tape/dynamic_test.go @@ -67,6 +67,65 @@ func TestEncodeDecodeAnyMap(test *testing.T) { if err != nil { test.Fatal(err) } } +func TestPeekSlice(test *testing.T) { + buffer := bytes.NewBuffer([]byte { + 2, byte(OTA.WithCN(3)), + 0, 0, 0, 1, byte(LI.WithCN(1)), + 0, 0x5, + 2, byte(LI.WithCN(1)), + 0, 0x17, + 0xAA, 0xAA, + }) + decoder := NewDecoder(buffer) + + elem, dimension, err := peekSlice(decoder, OTA.WithCN(0)) + if err != nil { test.Fatal(err) } + if elem != LI.WithCN(1) { + test.Fatalf("wrong element tag: %v %02X", elem, byte(elem)) + } + if got, correct := dimension, 2; got != correct { + test.Fatalf("wrong dimension: %d != %d", got, correct) + } +} + +func TestPeekSliceOnce(test *testing.T) { + buffer := bytes.NewBuffer([]byte { + 2, byte(OTA.WithCN(3)), + 0, 0, 0, 1, byte(LI.WithCN(1)), + 0, 0x5, + 2, byte(LI.WithCN(1)), + 0, 0x17, + 0xAA, 0xAA, + }) + decoder := NewDecoder(buffer) + + test.Log("--- stage 1") + elem, populated, n, err := peekSliceOnce(decoder, OTA.WithCN(0), 0) + if err != nil { test.Fatal(err) } + if elem != OTA.WithCN(3) { + test.Fatal("wrong element tag:", elem) + } + if !populated { + test.Fatal("wrong populated:", populated) + } + if got, correct := n, 2; got != correct { + test.Fatalf("wrong n: %d != %d", got, correct) + } + + test.Log("--- stage 2") + elem, populated, n, err = peekSliceOnce(decoder, elem, n) + if err != nil { test.Fatal(err) } + if elem != LI.WithCN(1) { + test.Fatal("wrong element tag:", elem) + } + if !populated { + test.Fatal("wrong populated:", populated) + } + if got, correct := n, 7; got != correct { + test.Fatalf("wrong n: %d != %d", got, correct) + } +} + func encAny(value any) ([]byte, Tag, int, error) { tag, err := TagAny(value) if err != nil { return nil, 0, 0, err }