sonic.go (4508B)
1 // +build amd64,go1.15,!go1.21 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 62 // configure decoder options: 63 if cfg.UseInt64 { 64 api.decoderOpts |= decoder.OptionUseInt64 65 } 66 if cfg.UseNumber { 67 api.decoderOpts |= decoder.OptionUseNumber 68 } 69 if cfg.DisallowUnknownFields { 70 api.decoderOpts |= decoder.OptionDisableUnknown 71 } 72 if cfg.CopyString { 73 api.decoderOpts |= decoder.OptionCopyString 74 } 75 if cfg.ValidateString { 76 api.decoderOpts |= decoder.OptionValidateString 77 } 78 return api 79 } 80 81 // Marshal is implemented by sonic 82 func (cfg frozenConfig) Marshal(val interface{}) ([]byte, error) { 83 return encoder.Encode(val, cfg.encoderOpts) 84 } 85 86 // MarshalToString is implemented by sonic 87 func (cfg frozenConfig) MarshalToString(val interface{}) (string, error) { 88 buf, err := encoder.Encode(val, cfg.encoderOpts) 89 return rt.Mem2Str(buf), err 90 } 91 92 // MarshalIndent is implemented by sonic 93 func (cfg frozenConfig) MarshalIndent(val interface{}, prefix, indent string) ([]byte, error) { 94 return encoder.EncodeIndented(val, prefix, indent, cfg.encoderOpts) 95 } 96 97 // UnmarshalFromString is implemented by sonic 98 func (cfg frozenConfig) UnmarshalFromString(buf string, val interface{}) error { 99 dec := decoder.NewDecoder(buf) 100 dec.SetOptions(cfg.decoderOpts) 101 err := dec.Decode(val) 102 103 /* check for errors */ 104 if err != nil { 105 return err 106 } 107 108 return dec.CheckTrailings() 109 } 110 111 // Unmarshal is implemented by sonic 112 func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error { 113 return cfg.UnmarshalFromString(string(buf), val) 114 } 115 116 // NewEncoder is implemented by sonic 117 func (cfg frozenConfig) NewEncoder(writer io.Writer) Encoder { 118 enc := encoder.NewStreamEncoder(writer) 119 enc.Opts = cfg.encoderOpts 120 return enc 121 } 122 123 // NewDecoder is implemented by sonic 124 func (cfg frozenConfig) NewDecoder(reader io.Reader) Decoder { 125 dec := decoder.NewStreamDecoder(reader) 126 dec.SetOptions(cfg.decoderOpts) 127 return dec 128 } 129 130 // Valid is implemented by sonic 131 func (cfg frozenConfig) Valid(data []byte) bool { 132 ok, _ := encoder.Valid(data) 133 return ok 134 } 135 136 // Pretouch compiles vt ahead-of-time to avoid JIT compilation on-the-fly, in 137 // order to reduce the first-hit latency. 138 // 139 // Opts are the compile options, for example, "option.WithCompileRecursiveDepth" is 140 // a compile option to set the depth of recursive compile for the nested struct type. 141 func Pretouch(vt reflect.Type, opts ...option.CompileOption) error { 142 if err := encoder.Pretouch(vt, opts...); err != nil { 143 return err 144 } 145 if err := decoder.Pretouch(vt, opts...); err != nil { 146 return err 147 } 148 // to pretouch the corresponding pointer type as well 149 if vt.Kind() == reflect.Ptr { 150 vt = vt.Elem() 151 } else { 152 vt = reflect.PtrTo(vt) 153 } 154 if err := encoder.Pretouch(vt, opts...); err != nil { 155 return err 156 } 157 if err := decoder.Pretouch(vt, opts...); err != nil { 158 return err 159 } 160 return nil 161 }