diff --git a/pkg/encoders/event/event.go b/pkg/encoders/event/event.go index 90b6a98..31caf39 100644 --- a/pkg/encoders/event/event.go +++ b/pkg/encoders/event/event.go @@ -111,27 +111,11 @@ func (ev *E) MarshalJSON() (b []byte, err error) { b = ints.New(ev.Kind).Marshal(b) b = append(b, `,"`...) b = append(b, jTags...) - b = append(b, `":[`...) + b = append(b, `":`...) if ev.Tags != nil { - lts := len(*ev.Tags) - 1 - for i, tt := range *ev.Tags { - b = append(b, '[') - lt := len(tt.T) - 1 - for j, t := range tt.T { - b = append(b, '"') - b = append(b, t...) - b = append(b, '"') - if j < lt { - b = append(b, ',') - } - } - b = append(b, ']') - if i < lts { - b = append(b, ',') - } - } + b = ev.Tags.Marshal(b) } - b = append(b, `],"`...) + b = append(b, `,"`...) b = append(b, jContent...) b = append(b, `":"`...) // it can happen the slice has insufficient capacity to hold the content AND @@ -175,6 +159,7 @@ func (ev *E) UnmarshalJSON(b []byte) (err error) { goto BetweenKeys } } + log.I.F("start") goto eof BetweenKeys: for ; len(b) > 0; b = b[1:] { @@ -187,6 +172,7 @@ BetweenKeys: goto InKey } } + log.I.F("BetweenKeys") goto eof InKey: for ; len(b) > 0; b = b[1:] { @@ -196,6 +182,7 @@ InKey: } key = append(key, b[0]) } + log.I.F("InKey") goto eof InKV: for ; len(b) > 0; b = b[1:] { @@ -208,6 +195,7 @@ InKV: goto InVal } } + log.I.F("InKV") goto eof InVal: // Skip whitespace before value @@ -298,9 +286,11 @@ InVal: if !utils.FastEqual(jCreatedAt, key) { goto invalid } - if b, err = ints.New(0).Unmarshal(b); chk.T(err) { + i := ints.New(0) + if b, err = i.Unmarshal(b); chk.T(err) { return } + ev.CreatedAt = i.Int64() goto BetweenKV } else { goto invalid @@ -315,7 +305,6 @@ BetweenKV: if isWhitespace(b[0]) { continue } - switch { case len(b) == 0: return diff --git a/pkg/encoders/event/event_test.go b/pkg/encoders/event/event_test.go index 6a77e6e..ddcedb1 100644 --- a/pkg/encoders/event/event_test.go +++ b/pkg/encoders/event/event_test.go @@ -1,16 +1,21 @@ package event import ( + "bufio" + "bytes" "encoding/json" "testing" "time" "lol.mleku.dev/chk" + "lol.mleku.dev/log" "lukechampine.com/frand" + "next.orly.dev/pkg/encoders/event/examples" "next.orly.dev/pkg/encoders/hex" "next.orly.dev/pkg/encoders/tag" "next.orly.dev/pkg/utils" "next.orly.dev/pkg/utils/bufpool" + "next.orly.dev/pkg/utils/units" ) func TestMarshalJSONUnmarshalJSON(t *testing.T) { @@ -35,13 +40,12 @@ func TestMarshalJSONUnmarshalJSON(t *testing.T) { `) ev.Sig = frand.Bytes(64) // log.I.S(ev) - b, err := ev.MarshalJSON() + // b, err := ev.MarshalJSON() + var err error + var b []byte if b, err = json.Marshal(ev); chk.E(err) { t.Fatal(err) } - if err != nil { - t.Fatal(err) - } var bc []byte bc = append(bc, b...) ev2 := New() @@ -49,7 +53,7 @@ func TestMarshalJSONUnmarshalJSON(t *testing.T) { t.Fatal(err) } var b2 []byte - if b2, err = ev.MarshalJSON(); err != nil { + if b2, err = json.Marshal(ev2); err != nil { t.Fatal(err) } if !utils.FastEqual(bc, b2) { @@ -65,5 +69,30 @@ func TestMarshalJSONUnmarshalJSON(t *testing.T) { } func TestExamplesCache(t *testing.T) { - + scanner := bufio.NewScanner(bytes.NewBuffer(examples.Cache)) + scanner.Buffer(make([]byte, 0, 4*units.Mb), 4*units.Mb) + var err error + for scanner.Scan() { + b := scanner.Bytes() + c := bufpool.Get() + c = c[:0] + c = append(c, b...) + ev := New() + if err = ev.UnmarshalJSON(b); chk.E(err) { + t.Fatal(err) + } + var b2 []byte + if b2, err = ev.MarshalJSON(); err != nil { + t.Fatal(err) + } + if !utils.FastEqual(c, b2) { + log.I.F("\n%s\n%s", c, b2) + t.Fatalf("failed to re-marshal back original") + } + ev.Free() + // Don't return scanner.Bytes() to the pool as it's not a buffer we own + // bufpool.PutBytes(b) + bufpool.PutBytes(b2) + bufpool.PutBytes(c) + } } diff --git a/pkg/encoders/ints/ints.go b/pkg/encoders/ints/ints.go index 2043d82..5d120c0 100644 --- a/pkg/encoders/ints/ints.go +++ b/pkg/encoders/ints/ints.go @@ -109,6 +109,7 @@ func (n *T) Unmarshal(b []byte) (r []byte, err error) { break } } + // log.I.F("%s", b) if len(b) == 0 { err = io.EOF return @@ -116,6 +117,7 @@ func (n *T) Unmarshal(b []byte) (r []byte, err error) { // count the digits for ; sLen < len(b) && b[sLen] >= zero && b[sLen] <= nine && b[sLen] != ','; sLen++ { } + // log.I.F("%s", b[:sLen]) if sLen == 0 { err = errorf.E("zero length number") return @@ -127,9 +129,13 @@ func (n *T) Unmarshal(b []byte) (r []byte, err error) { // the length of the string found r = b[sLen:] b = b[:sLen] + // log.I.F("\n%s\n%s", b, r) + n.N = uint64(b[0]) - zero + b = b[1:] for _, ch := range b { ch -= zero n.N = n.N*10 + uint64(ch) } + // log.I.F("%d", n.N) return } diff --git a/pkg/encoders/tag/tag.go b/pkg/encoders/tag/tag.go index 28512b6..e946fb6 100644 --- a/pkg/encoders/tag/tag.go +++ b/pkg/encoders/tag/tag.go @@ -33,8 +33,7 @@ func (t *T) Free() { // Marshal encodes a tag.T as standard minified JSON array of strings. // // Call bufpool.PutBytes(b) to return the buffer to the bufpool after use. -func (t *T) Marshal() (b []byte) { - dst := t.b +func (t *T) Marshal(dst []byte) (b []byte) { dst = append(dst, '[') for i, s := range t.T { dst = text.AppendQuote(dst, s, text.NostrEscape) diff --git a/pkg/encoders/tag/tags.go b/pkg/encoders/tag/tags.go index f5def4c..425007c 100644 --- a/pkg/encoders/tag/tags.go +++ b/pkg/encoders/tag/tags.go @@ -16,7 +16,19 @@ func (s *S) MarshalJSON() (b []byte, err error) { b = bufpool.Get() b = append(b, '[') for i, ss := range *s { - b = append(b, ss.Marshal()...) + b = ss.Marshal(b) + if i < len(*s)-1 { + b = append(b, ',') + } + } + b = append(b, ']') + return +} + +func (s *S) Marshal(dst []byte) (b []byte) { + b = append(dst, '[') + for i, ss := range *s { + b = ss.Marshal(b) if i < len(*s)-1 { b = append(b, ',') } diff --git a/pkg/utils/bufpool/bufpool.go b/pkg/utils/bufpool/bufpool.go index 83e376c..5d82be2 100644 --- a/pkg/utils/bufpool/bufpool.go +++ b/pkg/utils/bufpool/bufpool.go @@ -74,5 +74,6 @@ func PutBytes(b []byte) { return fmt.Sprintf("returning bytes to buffer: %p", ptr) }, ) + b = b[:0] Put(b) }