From 851452243879498117cd7e71ac12856af44657cb Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 14 Feb 2023 11:44:36 -0700 Subject: reencode: Don't have the ReEncoderConfig member be public --- ReleaseNotes.md | 24 ++++++++++++++---------- compat/json/compat.go | 43 +++++++++++++++++++++++++++---------------- encode.go | 2 +- reencode.go | 38 +++++++++++++++++++------------------- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index e00bf10..bee16c4 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -4,16 +4,20 @@ User-facing changes: - - `Number` and `RawMessage` type aliases are now available, so that - a user of lowmemjson's native APIs does not need to import - `encoding/json` or compat/json in order to use them. - - - Encoder, ReEncoder: If there was an error writing to the output - stream, it may have returned a `*ReEncodeSyntaxError` even though - it's not a syntax issue, or may have returned the underlying - error without wrapping it. If there is an error writing to the - output, Encoder and ReEncoder now return `*EncodeWriteError` and - `*ReEncodeWriteError` respectively. + - Change: ReEncoder: The ReEncoderConfig struct member is no longer + public. + + - Feature: `Number` and `RawMessage` type aliases are now + available, so that a user of lowmemjson's native APIs does not + need to import `encoding/json` or compat/json in order to use + them. + + - Bigfix: Encoder, ReEncoder: If there was an error writing to the + output stream, it may have returned a `*ReEncodeSyntaxError` even + though it's not a syntax issue, or may have returned the + underlying error without wrapping it. If there is an error + writing to the output, Encoder and ReEncoder now return + `*EncodeWriteError` and `*ReEncodeWriteError` respectively. # v0.3.5 (2023-02-10) diff --git a/compat/json/compat.go b/compat/json/compat.go index 3678135..c96470d 100644 --- a/compat/json/compat.go +++ b/compat/json/compat.go @@ -72,8 +72,11 @@ func Marshal(v any) ([]byte, error) { } type Encoder struct { - out io.Writer - buf bytes.Buffer + out io.Writer + buf bytes.Buffer + + cfg lowmemjson.ReEncoderConfig + encoder *lowmemjson.Encoder formatter *lowmemjson.ReEncoder } @@ -81,17 +84,23 @@ type Encoder struct { func NewEncoder(w io.Writer) *Encoder { ret := &Encoder{ out: w, - } - ret.formatter = lowmemjson.NewReEncoder(&ret.buf, lowmemjson.ReEncoderConfig{ - AllowMultipleValues: true, - Compact: true, - ForceTrailingNewlines: true, - }) - ret.encoder = lowmemjson.NewEncoder(ret.formatter) + cfg: lowmemjson.ReEncoderConfig{ + AllowMultipleValues: true, + + Compact: true, + ForceTrailingNewlines: true, + }, + } + ret.refreshConfig() return ret } +func (enc *Encoder) refreshConfig() { + enc.formatter = lowmemjson.NewReEncoder(&enc.buf, enc.cfg) + enc.encoder = lowmemjson.NewEncoder(enc.formatter) +} + func (enc *Encoder) Encode(v any) error { if err := convertEncodeError(enc.encoder.Encode(v)); err != nil { enc.buf.Reset() @@ -104,17 +113,19 @@ func (enc *Encoder) Encode(v any) error { } func (enc *Encoder) SetEscapeHTML(on bool) { - var escaper lowmemjson.BackslashEscaper - if !on { - escaper = lowmemjson.EscapeDefaultNonHTMLSafe + if on { + enc.cfg.BackslashEscape = lowmemjson.EscapeDefault + } else { + enc.cfg.BackslashEscape = lowmemjson.EscapeDefaultNonHTMLSafe } - enc.formatter.BackslashEscape = escaper + enc.refreshConfig() } func (enc *Encoder) SetIndent(prefix, indent string) { - enc.formatter.Compact = prefix == "" && indent == "" - enc.formatter.Prefix = prefix - enc.formatter.Indent = indent + enc.cfg.Compact = prefix == "" && indent == "" + enc.cfg.Prefix = prefix + enc.cfg.Indent = indent + enc.refreshConfig() } // ReEncode wrappers ///////////////////////////////////////////////// diff --git a/encode.go b/encode.go index ebb4568..2e10134 100644 --- a/encode.go +++ b/encode.go @@ -83,7 +83,7 @@ func (enc *Encoder) Encode(obj any) (err error) { if enc.isRoot { enc.w.par.Reset() } - escaper := enc.w.BackslashEscape + escaper := enc.w.cfg.BackslashEscape if escaper == nil { escaper = EscapeDefault } diff --git a/reencode.go b/reencode.go index f100275..32796f6 100644 --- a/reencode.go +++ b/reencode.go @@ -72,9 +72,9 @@ type ReEncoderConfig struct { // bufio.Writer. func NewReEncoder(out io.Writer, cfg ReEncoderConfig) *ReEncoder { return &ReEncoder{ - ReEncoderConfig: cfg, - out: fastio.NewAllWriter(out), - specu: new(speculation), + cfg: cfg, + out: fastio.NewAllWriter(out), + specu: new(speculation), } } @@ -87,7 +87,7 @@ func NewReEncoder(out io.Writer, cfg ReEncoderConfig) *ReEncoder { // // The memory use of a ReEncoder is O(CompactIfUnder+depth). type ReEncoder struct { - ReEncoderConfig + cfg ReEncoderConfig out fastio.AllWriter // state: .Write's and .WriteString's utf8-decoding buffer @@ -239,7 +239,7 @@ func (enc *ReEncoder) Close() error { } return enc.err } - if enc.AllowMultipleValues { + if enc.cfg.AllowMultipleValues { enc.par.Reset() } } @@ -283,7 +283,7 @@ rehandle: return enc.written, enc.err } if t == jsonparse.RuneTypeEOF { - if enc.AllowMultipleValues && len(enc.barriers) == 0 { + if enc.cfg.AllowMultipleValues && len(enc.barriers) == 0 { enc.par.Reset() goto rehandle } else { @@ -328,7 +328,7 @@ func (enc *ReEncoder) stackSize() int { } func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) error { - if enc.CompactIfUnder == 0 || enc.Compact || enc.Indent == "" { + if enc.cfg.CompactIfUnder == 0 || enc.cfg.Compact || enc.cfg.Indent == "" { return enc.handleRuneNoSpeculation(c, t) } @@ -342,10 +342,10 @@ func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) er enc.specu.speculating = true enc.specu.endWhenStackSize = stackSize - 1 enc.specu.fmt = ReEncoder{ - ReEncoderConfig: enc.ReEncoderConfig, - out: &enc.specu.compact, + cfg: enc.cfg, + out: &enc.specu.compact, } - enc.specu.fmt.Compact = true + enc.specu.fmt.cfg.Compact = true enc.specu.buf = append(enc.specu.buf, inputTuple{ c: c, t: t, @@ -369,7 +369,7 @@ func (enc *ReEncoder) handleRune(c rune, t jsonparse.RuneType, stackSize int) er return err } switch { - case enc.specu.compact.Len() >= enc.CompactIfUnder: // stop speculating; use indent + case enc.specu.compact.Len() >= enc.cfg.CompactIfUnder: // stop speculating; use indent buf := append([]inputTuple(nil), enc.specu.buf...) enc.specu.Reset() if err := enc.handleRuneMain(buf[0].c, buf[0].t); err != nil { @@ -414,7 +414,7 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) if err := enc.emitByte('\n'); err != nil { return err, false } - case enc.Indent != "" && !enc.Compact: + case enc.cfg.Indent != "" && !enc.cfg.Compact: if err := enc.emitByte('\n'); err != nil { return err, false } @@ -458,11 +458,11 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) // whitespace switch { - case enc.Compact: + case enc.cfg.Compact: if t == jsonparse.RuneTypeSpace { return nil, false } - case enc.Indent != "": + case enc.cfg.Indent != "": switch t { case jsonparse.RuneTypeSpace: // let us manage whitespace, don't pass it through @@ -500,7 +500,7 @@ func (enc *ReEncoder) handleRunePre(c rune, t jsonparse.RuneType) (error, bool) // handleRuneMain handles the new rune itself, not buffered things. func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { - escaper := enc.BackslashEscape + escaper := enc.cfg.BackslashEscape if escaper == nil { escaper = EscapeDefault } @@ -549,7 +549,7 @@ func (enc *ReEncoder) handleRuneMain(c rune, t jsonparse.RuneType) error { case jsonparse.RuneTypeEOF: // EOF implied by the start of the next top-level value enc.wasNumber = enc.lastNonSpace.IsNumber() switch { - case enc.ForceTrailingNewlines && len(enc.barriers) == 0: + case enc.cfg.ForceTrailingNewlines && len(enc.barriers) == 0: t = jsonparse.RuneTypeError // enc.lastNonSpace : an NL isn't needed (we already printed one) err = enc.emitByte('\n') default: @@ -585,13 +585,13 @@ func (enc *ReEncoder) emitNlIndent() error { if err := enc.emitByte('\n'); err != nil { return err } - if enc.Prefix != "" { - if err := enc.emit(enc.out.WriteString(enc.Prefix)); err != nil { + if enc.cfg.Prefix != "" { + if err := enc.emit(enc.out.WriteString(enc.cfg.Prefix)); err != nil { return err } } for i := 0; i < enc.curIndent; i++ { - if err := enc.emit(enc.out.WriteString(enc.Indent)); err != nil { + if err := enc.emit(enc.out.WriteString(enc.cfg.Indent)); err != nil { return err } } -- cgit v1.1-4-g5e80