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