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