stream.go raw

   1  /*
   2   * Copyright 2021 ByteDance Inc.
   3   *
   4   * Licensed under the Apache License, Version 2.0 (the "License");
   5   * you may not use this file except in compliance with the License.
   6   * You may obtain a copy of the License at
   7   *
   8   *     http://www.apache.org/licenses/LICENSE-2.0
   9   *
  10   * Unless required by applicable law or agreed to in writing, software
  11   * distributed under the License is distributed on an "AS IS" BASIS,
  12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13   * See the License for the specific language governing permissions and
  14   * limitations under the License.
  15   */
  16  
  17  package encoder
  18  
  19  import (
  20  	"encoding/json"
  21  	"io"
  22  
  23  	"github.com/bytedance/sonic/internal/encoder/vars"
  24  )
  25  
  26  // StreamEncoder uses io.Writer as input.
  27  type StreamEncoder struct {
  28      w io.Writer
  29      Encoder
  30  }
  31  
  32  // NewStreamEncoder adapts to encoding/json.NewDecoder API.
  33  //
  34  // NewStreamEncoder returns a new encoder that write to w.
  35  func NewStreamEncoder(w io.Writer) *StreamEncoder {
  36      return &StreamEncoder{w: w}
  37  }
  38  
  39  // Encode encodes interface{} as JSON to io.Writer
  40  func (enc *StreamEncoder) Encode(val interface{}) (err error) {
  41      out := vars.NewBytes()
  42  
  43      /* encode into the buffer */
  44      err = EncodeInto(out, val, enc.Opts)
  45      if err != nil {
  46          goto free_bytes
  47      }
  48  
  49      if enc.indent != "" || enc.prefix != "" {
  50          /* indent the JSON */
  51          buf := vars.NewBuffer()
  52          err = json.Indent(buf, *out, enc.prefix, enc.indent)
  53          if err != nil {
  54              vars.FreeBuffer(buf)
  55              goto free_bytes
  56          }
  57  
  58          // according to standard library, terminate each value with a newline...
  59          if enc.Opts & NoEncoderNewline == 0 {
  60              buf.WriteByte('\n')
  61          }
  62  
  63          /* copy into io.Writer */
  64          _, err = io.Copy(enc.w, buf)
  65          if err != nil {
  66              vars.FreeBuffer(buf)
  67              goto free_bytes
  68          }
  69  
  70      } else {
  71          /* copy into io.Writer */
  72          var n int
  73          buf := *out
  74          for len(buf) > 0 {
  75              n, err = enc.w.Write(buf)
  76              buf = buf[n:]
  77              if err != nil {
  78                  goto free_bytes
  79              }
  80          }
  81  
  82          // according to standard library, terminate each value with a newline...
  83          if enc.Opts & NoEncoderNewline == 0 {
  84              enc.w.Write([]byte{'\n'})
  85          }
  86      }
  87  
  88  free_bytes:
  89      vars.FreeBytes(out)
  90      return err
  91  }
  92