github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/sonic.go (about) 1 // +build amd64,go1.16,!go1.23 2 3 /* 4 * Copyright 2021 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 //go:generate make 20 package sonic 21 22 import ( 23 `io` 24 `reflect` 25 26 `github.com/bytedance/sonic/decoder` 27 `github.com/bytedance/sonic/encoder` 28 `github.com/bytedance/sonic/option` 29 `github.com/bytedance/sonic/internal/rt` 30 ) 31 32 type frozenConfig struct { 33 Config 34 encoderOpts encoder.Options 35 decoderOpts decoder.Options 36 } 37 38 // Froze convert the Config to API 39 func (cfg Config) Froze() API { 40 api := &frozenConfig{Config: cfg} 41 42 // configure encoder options: 43 if cfg.EscapeHTML { 44 api.encoderOpts |= encoder.EscapeHTML 45 } 46 if cfg.SortMapKeys { 47 api.encoderOpts |= encoder.SortMapKeys 48 } 49 if cfg.CompactMarshaler { 50 api.encoderOpts |= encoder.CompactMarshaler 51 } 52 if cfg.NoQuoteTextMarshaler { 53 api.encoderOpts |= encoder.NoQuoteTextMarshaler 54 } 55 if cfg.NoNullSliceOrMap { 56 api.encoderOpts |= encoder.NoNullSliceOrMap 57 } 58 if cfg.ValidateString { 59 api.encoderOpts |= encoder.ValidateString 60 } 61 if cfg.NoValidateJSONMarshaler { 62 api.encoderOpts |= encoder.NoValidateJSONMarshaler 63 } 64 if cfg.NoEncoderNewline { 65 api.encoderOpts |= encoder.NoEncoderNewline 66 } 67 68 // configure decoder options: 69 if cfg.UseInt64 { 70 api.decoderOpts |= decoder.OptionUseInt64 71 } 72 if cfg.UseNumber { 73 api.decoderOpts |= decoder.OptionUseNumber 74 } 75 if cfg.DisallowUnknownFields { 76 api.decoderOpts |= decoder.OptionDisableUnknown 77 } 78 if cfg.CopyString { 79 api.decoderOpts |= decoder.OptionCopyString 80 } 81 if cfg.ValidateString { 82 api.decoderOpts |= decoder.OptionValidateString 83 } 84 return api 85 } 86 87 // Marshal is implemented by sonic 88 func (cfg frozenConfig) Marshal(val interface{}) ([]byte, error) { 89 return encoder.Encode(val, cfg.encoderOpts) 90 } 91 92 // MarshalToString is implemented by sonic 93 func (cfg frozenConfig) MarshalToString(val interface{}) (string, error) { 94 buf, err := encoder.Encode(val, cfg.encoderOpts) 95 return rt.Mem2Str(buf), err 96 } 97 98 // MarshalIndent is implemented by sonic 99 func (cfg frozenConfig) MarshalIndent(val interface{}, prefix, indent string) ([]byte, error) { 100 return encoder.EncodeIndented(val, prefix, indent, cfg.encoderOpts) 101 } 102 103 // UnmarshalFromString is implemented by sonic 104 func (cfg frozenConfig) UnmarshalFromString(buf string, val interface{}) error { 105 dec := decoder.NewDecoder(buf) 106 dec.SetOptions(cfg.decoderOpts) 107 err := dec.Decode(val) 108 109 /* check for errors */ 110 if err != nil { 111 return err 112 } 113 114 return dec.CheckTrailings() 115 } 116 117 // Unmarshal is implemented by sonic 118 func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error { 119 return cfg.UnmarshalFromString(string(buf), val) 120 } 121 122 // NewEncoder is implemented by sonic 123 func (cfg frozenConfig) NewEncoder(writer io.Writer) Encoder { 124 enc := encoder.NewStreamEncoder(writer) 125 enc.Opts = cfg.encoderOpts 126 return enc 127 } 128 129 // NewDecoder is implemented by sonic 130 func (cfg frozenConfig) NewDecoder(reader io.Reader) Decoder { 131 dec := decoder.NewStreamDecoder(reader) 132 dec.SetOptions(cfg.decoderOpts) 133 return dec 134 } 135 136 // Valid is implemented by sonic 137 func (cfg frozenConfig) Valid(data []byte) bool { 138 ok, _ := encoder.Valid(data) 139 return ok 140 } 141 142 // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in 143 // order to reduce the first-hit latency. 144 // 145 // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is 146 // a compile option to set the depth of recursive compile for the nested struct type. 147 func Pretouch(vt reflect.Type, opts ...option.CompileOption) error { 148 if err := encoder.Pretouch(vt, opts...); err != nil { 149 return err 150 } 151 if err := decoder.Pretouch(vt, opts...); err != nil { 152 return err 153 } 154 // to pretouch the corresponding pointer type as well 155 if vt.Kind() == reflect.Ptr { 156 vt = vt.Elem() 157 } else { 158 vt = reflect.PtrTo(vt) 159 } 160 if err := encoder.Pretouch(vt, opts...); err != nil { 161 return err 162 } 163 if err := decoder.Pretouch(vt, opts...); err != nil { 164 return err 165 } 166 return nil 167 }