...

Source file src/github.com/bytedance/sonic/encoder/encoder_compat.go

Documentation: github.com/bytedance/sonic/encoder

     1  // +build !amd64 !go1.16 go1.23
     2  
     3  /*
     4  * Copyright 2023 ByteDance Inc.
     5  *
     6  * Licensed under the Apache License, Version 2.0 (the "License");
     7  * you may not use this file except in compliance with the License.
     8  * You may obtain a copy of the License at
     9  *
    10  *     http://www.apache.org/licenses/LICENSE-2.0
    11  *
    12  * Unless required by applicable law or agreed to in writing, software
    13  * distributed under the License is distributed on an "AS IS" BASIS,
    14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  * See the License for the specific language governing permissions and
    16  * limitations under the License.
    17  */
    18  
    19  package encoder
    20  
    21  import (
    22     `io`
    23      `bytes`
    24      `encoding/json`
    25      `reflect`
    26  
    27      `github.com/bytedance/sonic/option`
    28  )
    29  
    30  func init() {
    31      println("WARNING: sonic only supports Go1.16~1.22 && CPU amd64, but your environment is not suitable")
    32  }
    33  
    34  // Options is a set of encoding options.
    35  type Options uint64
    36  
    37  const (
    38      bitSortMapKeys          = iota
    39      bitEscapeHTML          
    40      bitCompactMarshaler
    41      bitNoQuoteTextMarshaler
    42      bitNoNullSliceOrMap
    43      bitValidateString
    44      bitNoValidateJSONMarshaler
    45      bitNoEncoderNewline
    46  
    47      // used for recursive compile
    48      bitPointerValue = 63
    49  )
    50  
    51  const (
    52      // SortMapKeys indicates that the keys of a map needs to be sorted 
    53      // before serializing into JSON.
    54      // WARNING: This hurts performance A LOT, USE WITH CARE.
    55      SortMapKeys          Options = 1 << bitSortMapKeys
    56  
    57      // EscapeHTML indicates encoder to escape all HTML characters 
    58      // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).
    59      // WARNING: This hurts performance A LOT, USE WITH CARE.
    60      EscapeHTML           Options = 1 << bitEscapeHTML
    61  
    62      // CompactMarshaler indicates that the output JSON from json.Marshaler 
    63      // is always compact and needs no validation 
    64      CompactMarshaler     Options = 1 << bitCompactMarshaler
    65  
    66      // NoQuoteTextMarshaler indicates that the output text from encoding.TextMarshaler 
    67      // is always escaped string and needs no quoting
    68      NoQuoteTextMarshaler Options = 1 << bitNoQuoteTextMarshaler
    69  
    70      // NoNullSliceOrMap indicates all empty Array or Object are encoded as '[]' or '{}',
    71      // instead of 'null'
    72      NoNullSliceOrMap     Options = 1 << bitNoNullSliceOrMap
    73  
    74      // ValidateString indicates that encoder should validate the input string
    75      // before encoding it into JSON.
    76      ValidateString       Options = 1 << bitValidateString
    77  
    78      // NoValidateJSONMarshaler indicates that the encoder should not validate the output string
    79      // after encoding the JSONMarshaler to JSON.
    80      NoValidateJSONMarshaler Options = 1 << bitNoValidateJSONMarshaler
    81  
    82      // NoEncoderNewline indicates that the encoder should not add a newline after every message
    83      NoEncoderNewline Options = 1 << bitNoEncoderNewline
    84    
    85      // CompatibleWithStd is used to be compatible with std encoder.
    86      CompatibleWithStd Options = SortMapKeys | EscapeHTML | CompactMarshaler
    87  )
    88  
    89  // Encoder represents a specific set of encoder configurations.
    90  type Encoder struct {
    91      Opts Options
    92      prefix string
    93      indent string
    94  }
    95  
    96  // Encode returns the JSON encoding of v.
    97  func (self *Encoder) Encode(v interface{}) ([]byte, error) {
    98      if self.indent != "" || self.prefix != "" { 
    99          return EncodeIndented(v, self.prefix, self.indent, self.Opts)
   100      }
   101      return Encode(v, self.Opts)
   102  }
   103  
   104  // SortKeys enables the SortMapKeys option.
   105  func (self *Encoder) SortKeys() *Encoder {
   106      self.Opts |= SortMapKeys
   107      return self
   108  }
   109  
   110  // SetEscapeHTML specifies if option EscapeHTML opens
   111  func (self *Encoder) SetEscapeHTML(f bool) {
   112      if f {
   113          self.Opts |= EscapeHTML
   114      } else {
   115          self.Opts &= ^EscapeHTML
   116      }
   117  }
   118  
   119  // SetValidateString specifies if option ValidateString opens
   120  func (self *Encoder) SetValidateString(f bool) {
   121      if f {
   122          self.Opts |= ValidateString
   123      } else {
   124          self.Opts &= ^ValidateString
   125      }
   126  }
   127  
   128  // SetNoValidateJSONMarshaler specifies if option NoValidateJSONMarshaler opens
   129  func (self *Encoder) SetNoValidateJSONMarshaler(f bool) {
   130      if f {
   131          self.Opts |= NoValidateJSONMarshaler
   132      } else {
   133          self.Opts &= ^NoValidateJSONMarshaler
   134      }
   135  }
   136  
   137  // SetNoEncoderNewline specifies if option NoEncoderNewline opens
   138  func (self *Encoder) SetNoEncoderNewline(f bool) {
   139      if f {
   140          self.Opts |= NoEncoderNewline
   141      } else {
   142          self.Opts &= ^NoEncoderNewline
   143      }
   144  }
   145  
   146  // SetCompactMarshaler specifies if option CompactMarshaler opens
   147  func (self *Encoder) SetCompactMarshaler(f bool) {
   148      if f {
   149          self.Opts |= CompactMarshaler
   150      } else {
   151          self.Opts &= ^CompactMarshaler
   152      }
   153  }
   154  
   155  // SetNoQuoteTextMarshaler specifies if option NoQuoteTextMarshaler opens
   156  func (self *Encoder) SetNoQuoteTextMarshaler(f bool) {
   157      if f {
   158          self.Opts |= NoQuoteTextMarshaler
   159      } else {
   160          self.Opts &= ^NoQuoteTextMarshaler
   161      }
   162  }
   163  
   164  // SetIndent instructs the encoder to format each subsequent encoded
   165  // value as if indented by the package-level function EncodeIndent().
   166  // Calling SetIndent("", "") disables indentation.
   167  func (enc *Encoder) SetIndent(prefix, indent string) {
   168      enc.prefix = prefix
   169      enc.indent = indent
   170  }
   171  
   172  // Quote returns the JSON-quoted version of s.
   173  func Quote(s string) string {
   174      /* check for empty string */
   175      if s == "" {
   176          return `""`
   177      }
   178  
   179      out, _ := json.Marshal(s)
   180      return string(out)
   181  }
   182  
   183  // Encode returns the JSON encoding of val, encoded with opts.
   184  func Encode(val interface{}, opts Options) ([]byte, error) {
   185     return json.Marshal(val)
   186  }
   187  
   188  // EncodeInto is like Encode but uses a user-supplied buffer instead of allocating
   189  // a new one.
   190  func EncodeInto(buf *[]byte, val interface{}, opts Options) error {
   191     if buf == nil {
   192         panic("user-supplied buffer buf is nil")
   193     }
   194     w := bytes.NewBuffer(*buf)
   195     enc := json.NewEncoder(w)
   196     enc.SetEscapeHTML((opts & EscapeHTML) != 0)
   197     err := enc.Encode(val)
   198     *buf = w.Bytes()
   199     return err
   200  }
   201  
   202  // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
   203  // characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
   204  // so that the JSON will be safe to embed inside HTML <script> tags.
   205  // For historical reasons, web browsers don't honor standard HTML
   206  // escaping within <script> tags, so an alternative JSON encoding must
   207  // be used.
   208  func HTMLEscape(dst []byte, src []byte) []byte {
   209     d := bytes.NewBuffer(dst)
   210     json.HTMLEscape(d, src)
   211     return d.Bytes()
   212  }
   213  
   214  // EncodeIndented is like Encode but applies Indent to format the output.
   215  // Each JSON element in the output will begin on a new line beginning with prefix
   216  // followed by one or more copies of indent according to the indentation nesting.
   217  func EncodeIndented(val interface{}, prefix string, indent string, opts Options) ([]byte, error) {
   218     w := bytes.NewBuffer([]byte{})
   219     enc := json.NewEncoder(w)
   220     enc.SetEscapeHTML((opts & EscapeHTML) != 0)
   221     enc.SetIndent(prefix, indent)
   222     err := enc.Encode(val)
   223     out := w.Bytes()
   224     return out, err
   225  }
   226  
   227  // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
   228  // order to reduce the first-hit latency.
   229  //
   230  // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
   231  // a compile option to set the depth of recursive compile for the nested struct type.
   232  func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
   233     return nil
   234  }
   235  
   236  // Valid validates json and returns first non-blank character position,
   237  // if it is only one valid json value.
   238  // Otherwise returns invalid character position using start.
   239  //
   240  // Note: it does not check for the invalid UTF-8 characters.
   241  func Valid(data []byte) (ok bool, start int) {
   242     return json.Valid(data), 0
   243  }
   244  
   245  // StreamEncoder uses io.Writer as 
   246  type StreamEncoder = json.Encoder
   247  
   248  // NewStreamEncoder adapts to encoding/json.NewDecoder API.
   249  //
   250  // NewStreamEncoder returns a new encoder that write to w.
   251  func NewStreamEncoder(w io.Writer) *StreamEncoder {
   252     return json.NewEncoder(w)
   253  }
   254  
   255  

View as plain text