sonic.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // +build amd64,go1.16,!go1.22
  2. /*
  3. * Copyright 2021 ByteDance Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. //go:generate make
  18. package sonic
  19. import (
  20. `io`
  21. `reflect`
  22. `github.com/bytedance/sonic/decoder`
  23. `github.com/bytedance/sonic/encoder`
  24. `github.com/bytedance/sonic/option`
  25. `github.com/bytedance/sonic/internal/rt`
  26. )
  27. type frozenConfig struct {
  28. Config
  29. encoderOpts encoder.Options
  30. decoderOpts decoder.Options
  31. }
  32. // Froze convert the Config to API
  33. func (cfg Config) Froze() API {
  34. api := &frozenConfig{Config: cfg}
  35. // configure encoder options:
  36. if cfg.EscapeHTML {
  37. api.encoderOpts |= encoder.EscapeHTML
  38. }
  39. if cfg.SortMapKeys {
  40. api.encoderOpts |= encoder.SortMapKeys
  41. }
  42. if cfg.CompactMarshaler {
  43. api.encoderOpts |= encoder.CompactMarshaler
  44. }
  45. if cfg.NoQuoteTextMarshaler {
  46. api.encoderOpts |= encoder.NoQuoteTextMarshaler
  47. }
  48. if cfg.NoNullSliceOrMap {
  49. api.encoderOpts |= encoder.NoNullSliceOrMap
  50. }
  51. if cfg.ValidateString {
  52. api.encoderOpts |= encoder.ValidateString
  53. }
  54. if cfg.NoValidateJSONMarshaler {
  55. api.encoderOpts |= encoder.NoValidateJSONMarshaler
  56. }
  57. // configure decoder options:
  58. if cfg.UseInt64 {
  59. api.decoderOpts |= decoder.OptionUseInt64
  60. }
  61. if cfg.UseNumber {
  62. api.decoderOpts |= decoder.OptionUseNumber
  63. }
  64. if cfg.DisallowUnknownFields {
  65. api.decoderOpts |= decoder.OptionDisableUnknown
  66. }
  67. if cfg.CopyString {
  68. api.decoderOpts |= decoder.OptionCopyString
  69. }
  70. if cfg.ValidateString {
  71. api.decoderOpts |= decoder.OptionValidateString
  72. }
  73. return api
  74. }
  75. // Marshal is implemented by sonic
  76. func (cfg frozenConfig) Marshal(val interface{}) ([]byte, error) {
  77. return encoder.Encode(val, cfg.encoderOpts)
  78. }
  79. // MarshalToString is implemented by sonic
  80. func (cfg frozenConfig) MarshalToString(val interface{}) (string, error) {
  81. buf, err := encoder.Encode(val, cfg.encoderOpts)
  82. return rt.Mem2Str(buf), err
  83. }
  84. // MarshalIndent is implemented by sonic
  85. func (cfg frozenConfig) MarshalIndent(val interface{}, prefix, indent string) ([]byte, error) {
  86. return encoder.EncodeIndented(val, prefix, indent, cfg.encoderOpts)
  87. }
  88. // UnmarshalFromString is implemented by sonic
  89. func (cfg frozenConfig) UnmarshalFromString(buf string, val interface{}) error {
  90. dec := decoder.NewDecoder(buf)
  91. dec.SetOptions(cfg.decoderOpts)
  92. err := dec.Decode(val)
  93. /* check for errors */
  94. if err != nil {
  95. return err
  96. }
  97. return dec.CheckTrailings()
  98. }
  99. // Unmarshal is implemented by sonic
  100. func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error {
  101. return cfg.UnmarshalFromString(string(buf), val)
  102. }
  103. // NewEncoder is implemented by sonic
  104. func (cfg frozenConfig) NewEncoder(writer io.Writer) Encoder {
  105. enc := encoder.NewStreamEncoder(writer)
  106. enc.Opts = cfg.encoderOpts
  107. return enc
  108. }
  109. // NewDecoder is implemented by sonic
  110. func (cfg frozenConfig) NewDecoder(reader io.Reader) Decoder {
  111. dec := decoder.NewStreamDecoder(reader)
  112. dec.SetOptions(cfg.decoderOpts)
  113. return dec
  114. }
  115. // Valid is implemented by sonic
  116. func (cfg frozenConfig) Valid(data []byte) bool {
  117. ok, _ := encoder.Valid(data)
  118. return ok
  119. }
  120. // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in
  121. // order to reduce the first-hit latency.
  122. //
  123. // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is
  124. // a compile option to set the depth of recursive compile for the nested struct type.
  125. func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
  126. if err := encoder.Pretouch(vt, opts...); err != nil {
  127. return err
  128. }
  129. if err := decoder.Pretouch(vt, opts...); err != nil {
  130. return err
  131. }
  132. // to pretouch the corresponding pointer type as well
  133. if vt.Kind() == reflect.Ptr {
  134. vt = vt.Elem()
  135. } else {
  136. vt = reflect.PtrTo(vt)
  137. }
  138. if err := encoder.Pretouch(vt, opts...); err != nil {
  139. return err
  140. }
  141. if err := decoder.Pretouch(vt, opts...); err != nil {
  142. return err
  143. }
  144. return nil
  145. }