Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / go-openapi / swag / json.go
1 // Copyright 2015 go-swagger maintainers
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package swag
16
17 import (
18         "bytes"
19         "encoding/json"
20         "log"
21         "reflect"
22         "strings"
23         "sync"
24
25         "github.com/mailru/easyjson/jlexer"
26         "github.com/mailru/easyjson/jwriter"
27 )
28
29 // nullJSON represents a JSON object with null type
30 var nullJSON = []byte("null")
31
32 // DefaultJSONNameProvider the default cache for types
33 var DefaultJSONNameProvider = NewNameProvider()
34
35 const comma = byte(',')
36
37 var closers map[byte]byte
38
39 func init() {
40         closers = map[byte]byte{
41                 '{': '}',
42                 '[': ']',
43         }
44 }
45
46 type ejMarshaler interface {
47         MarshalEasyJSON(w *jwriter.Writer)
48 }
49
50 type ejUnmarshaler interface {
51         UnmarshalEasyJSON(w *jlexer.Lexer)
52 }
53
54 // WriteJSON writes json data, prefers finding an appropriate interface to short-circuit the marshaller
55 // so it takes the fastest option available.
56 func WriteJSON(data interface{}) ([]byte, error) {
57         if d, ok := data.(ejMarshaler); ok {
58                 jw := new(jwriter.Writer)
59                 d.MarshalEasyJSON(jw)
60                 return jw.BuildBytes()
61         }
62         if d, ok := data.(json.Marshaler); ok {
63                 return d.MarshalJSON()
64         }
65         return json.Marshal(data)
66 }
67
68 // ReadJSON reads json data, prefers finding an appropriate interface to short-circuit the unmarshaller
69 // so it takes the fastes option available
70 func ReadJSON(data []byte, value interface{}) error {
71         trimmedData := bytes.Trim(data, "\x00")
72         if d, ok := value.(ejUnmarshaler); ok {
73                 jl := &jlexer.Lexer{Data: trimmedData}
74                 d.UnmarshalEasyJSON(jl)
75                 return jl.Error()
76         }
77         if d, ok := value.(json.Unmarshaler); ok {
78                 return d.UnmarshalJSON(trimmedData)
79         }
80         return json.Unmarshal(trimmedData, value)
81 }
82
83 // DynamicJSONToStruct converts an untyped json structure into a struct
84 func DynamicJSONToStruct(data interface{}, target interface{}) error {
85         // TODO: convert straight to a json typed map  (mergo + iterate?)
86         b, err := WriteJSON(data)
87         if err != nil {
88                 return err
89         }
90         return ReadJSON(b, target)
91 }
92
93 // ConcatJSON concatenates multiple json objects efficiently
94 func ConcatJSON(blobs ...[]byte) []byte {
95         if len(blobs) == 0 {
96                 return nil
97         }
98
99         last := len(blobs) - 1
100         for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
101                 // strips trailing null objects
102                 last = last - 1
103                 if last < 0 {
104                         // there was nothing but "null"s or nil...
105                         return nil
106                 }
107         }
108         if last == 0 {
109                 return blobs[0]
110         }
111
112         var opening, closing byte
113         var idx, a int
114         buf := bytes.NewBuffer(nil)
115
116         for i, b := range blobs[:last+1] {
117                 if b == nil || bytes.Equal(b, nullJSON) {
118                         // a null object is in the list: skip it
119                         continue
120                 }
121                 if len(b) > 0 && opening == 0 { // is this an array or an object?
122                         opening, closing = b[0], closers[b[0]]
123                 }
124
125                 if opening != '{' && opening != '[' {
126                         continue // don't know how to concatenate non container objects
127                 }
128
129                 if len(b) < 3 { // yep empty but also the last one, so closing this thing
130                         if i == last && a > 0 {
131                                 if err := buf.WriteByte(closing); err != nil {
132                                         log.Println(err)
133                                 }
134                         }
135                         continue
136                 }
137
138                 idx = 0
139                 if a > 0 { // we need to join with a comma for everything beyond the first non-empty item
140                         if err := buf.WriteByte(comma); err != nil {
141                                 log.Println(err)
142                         }
143                         idx = 1 // this is not the first or the last so we want to drop the leading bracket
144                 }
145
146                 if i != last { // not the last one, strip brackets
147                         if _, err := buf.Write(b[idx : len(b)-1]); err != nil {
148                                 log.Println(err)
149                         }
150                 } else { // last one, strip only the leading bracket
151                         if _, err := buf.Write(b[idx:]); err != nil {
152                                 log.Println(err)
153                         }
154                 }
155                 a++
156         }
157         // somehow it ended up being empty, so provide a default value
158         if buf.Len() == 0 {
159                 if err := buf.WriteByte(opening); err != nil {
160                         log.Println(err)
161                 }
162                 if err := buf.WriteByte(closing); err != nil {
163                         log.Println(err)
164                 }
165         }
166         return buf.Bytes()
167 }
168
169 // ToDynamicJSON turns an object into a properly JSON typed structure
170 func ToDynamicJSON(data interface{}) interface{} {
171         // TODO: convert straight to a json typed map (mergo + iterate?)
172         b, err := json.Marshal(data)
173         if err != nil {
174                 log.Println(err)
175         }
176         var res interface{}
177         if err := json.Unmarshal(b, &res); err != nil {
178                 log.Println(err)
179         }
180         return res
181 }
182
183 // FromDynamicJSON turns an object into a properly JSON typed structure
184 func FromDynamicJSON(data, target interface{}) error {
185         b, err := json.Marshal(data)
186         if err != nil {
187                 log.Println(err)
188         }
189         return json.Unmarshal(b, target)
190 }
191
192 // NameProvider represents an object capabale of translating from go property names
193 // to json property names
194 // This type is thread-safe.
195 type NameProvider struct {
196         lock  *sync.Mutex
197         index map[reflect.Type]nameIndex
198 }
199
200 type nameIndex struct {
201         jsonNames map[string]string
202         goNames   map[string]string
203 }
204
205 // NewNameProvider creates a new name provider
206 func NewNameProvider() *NameProvider {
207         return &NameProvider{
208                 lock:  &sync.Mutex{},
209                 index: make(map[reflect.Type]nameIndex),
210         }
211 }
212
213 func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
214         for i := 0; i < tpe.NumField(); i++ {
215                 targetDes := tpe.Field(i)
216
217                 if targetDes.PkgPath != "" { // unexported
218                         continue
219                 }
220
221                 if targetDes.Anonymous { // walk embedded structures tree down first
222                         buildnameIndex(targetDes.Type, idx, reverseIdx)
223                         continue
224                 }
225
226                 if tag := targetDes.Tag.Get("json"); tag != "" {
227
228                         parts := strings.Split(tag, ",")
229                         if len(parts) == 0 {
230                                 continue
231                         }
232
233                         nm := parts[0]
234                         if nm == "-" {
235                                 continue
236                         }
237                         if nm == "" { // empty string means we want to use the Go name
238                                 nm = targetDes.Name
239                         }
240
241                         idx[nm] = targetDes.Name
242                         reverseIdx[targetDes.Name] = nm
243                 }
244         }
245 }
246
247 func newNameIndex(tpe reflect.Type) nameIndex {
248         var idx = make(map[string]string, tpe.NumField())
249         var reverseIdx = make(map[string]string, tpe.NumField())
250
251         buildnameIndex(tpe, idx, reverseIdx)
252         return nameIndex{jsonNames: idx, goNames: reverseIdx}
253 }
254
255 // GetJSONNames gets all the json property names for a type
256 func (n *NameProvider) GetJSONNames(subject interface{}) []string {
257         n.lock.Lock()
258         defer n.lock.Unlock()
259         tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
260         names, ok := n.index[tpe]
261         if !ok {
262                 names = n.makeNameIndex(tpe)
263         }
264
265         res := make([]string, 0, len(names.jsonNames))
266         for k := range names.jsonNames {
267                 res = append(res, k)
268         }
269         return res
270 }
271
272 // GetJSONName gets the json name for a go property name
273 func (n *NameProvider) GetJSONName(subject interface{}, name string) (string, bool) {
274         tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
275         return n.GetJSONNameForType(tpe, name)
276 }
277
278 // GetJSONNameForType gets the json name for a go property name on a given type
279 func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) {
280         n.lock.Lock()
281         defer n.lock.Unlock()
282         names, ok := n.index[tpe]
283         if !ok {
284                 names = n.makeNameIndex(tpe)
285         }
286         nme, ok := names.goNames[name]
287         return nme, ok
288 }
289
290 func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex {
291         names := newNameIndex(tpe)
292         n.index[tpe] = names
293         return names
294 }
295
296 // GetGoName gets the go name for a json property name
297 func (n *NameProvider) GetGoName(subject interface{}, name string) (string, bool) {
298         tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
299         return n.GetGoNameForType(tpe, name)
300 }
301
302 // GetGoNameForType gets the go name for a given type for a json property name
303 func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) {
304         n.lock.Lock()
305         defer n.lock.Unlock()
306         names, ok := n.index[tpe]
307         if !ok {
308                 names = n.makeNameIndex(tpe)
309         }
310         nme, ok := names.jsonNames[name]
311         return nme, ok
312 }