Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 1 | // Copyright 2019 CUE Authors |
| 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 openapi |
| 16 | |
| 17 | import "encoding/json" |
| 18 | |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 19 | // An OrderedMap is a set of key-value pairs that preserves the order in which |
| 20 | // items were added. It marshals to JSON as an object. |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 21 | type OrderedMap struct { |
| 22 | kvs []KeyValue |
| 23 | } |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 24 | |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 25 | // KeyValue associates a value with a key. |
| 26 | type KeyValue struct { |
| 27 | Key string |
| 28 | Value interface{} |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 29 | } |
| 30 | |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 31 | // Pairs returns the KeyValue pairs associated with m. |
| 32 | func (m *OrderedMap) Pairs() []KeyValue { |
| 33 | return m.kvs |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 34 | } |
| 35 | |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 36 | // Set sets a key value pair. If a pair with the same key already existed, it |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 37 | // will be replaced with the new value. Otherwise, the new value is added to |
| 38 | // the end. |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 39 | func (m *OrderedMap) Set(key string, value interface{}) { |
| 40 | for i, v := range m.kvs { |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 41 | if v.Key == key { |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 42 | m.kvs[i].Value = value |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 43 | return |
| 44 | } |
| 45 | } |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 46 | m.kvs = append(m.kvs, KeyValue{key, value}) |
| 47 | } |
| 48 | |
| 49 | // SetAll replaces existing key-value pairs with the given ones. The keys must |
| 50 | // be unique. |
| 51 | func (m *OrderedMap) SetAll(kvs []KeyValue) { |
| 52 | m.kvs = kvs |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 53 | } |
| 54 | |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 55 | // exists reports whether a key-value pair exists for the given key. |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 56 | func (m *OrderedMap) exists(key string) bool { |
| 57 | for _, v := range m.kvs { |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 58 | if v.Key == key { |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 59 | return true |
| 60 | } |
| 61 | } |
| 62 | return false |
| 63 | } |
| 64 | |
Marcel van Lohuizen | 35abfa7 | 2019-08-12 15:31:53 +0200 | [diff] [blame] | 65 | // exists reports whether a key-value pair exists for the given key. |
| 66 | func (m *OrderedMap) getMap(key string) *OrderedMap { |
| 67 | for _, v := range m.kvs { |
| 68 | if v.Key == key { |
| 69 | return v.Value.(*OrderedMap) |
| 70 | } |
| 71 | } |
| 72 | return nil |
| 73 | } |
| 74 | |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 75 | // MarshalJSON implements json.Marshaler. |
| 76 | func (m *OrderedMap) MarshalJSON() (b []byte, err error) { |
| 77 | // This is a pointer receiever to enforce that we only store pointers to |
| 78 | // OrderedMap in the output. |
| 79 | |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 80 | b = append(b, '{') |
Marcel van Lohuizen | c89f5a6 | 2019-07-04 10:41:18 +0200 | [diff] [blame] | 81 | for i, v := range m.kvs { |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 82 | if i > 0 { |
| 83 | b = append(b, ",\n"...) |
| 84 | } |
Marcel van Lohuizen | 35abfa7 | 2019-08-12 15:31:53 +0200 | [diff] [blame] | 85 | key, ferr := json.Marshal(v.Key) |
| 86 | if je, ok := ferr.(*json.MarshalerError); ok { |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 87 | return nil, je.Err |
| 88 | } |
| 89 | b = append(b, key...) |
| 90 | b = append(b, ": "...) |
| 91 | |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 92 | value, jerr := json.Marshal(v.Value) |
Marcel van Lohuizen | 35abfa7 | 2019-08-12 15:31:53 +0200 | [diff] [blame] | 93 | if je, ok := jerr.(*json.MarshalerError); ok { |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 94 | err = jerr |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 95 | value, _ = json.Marshal(je.Err.Error()) |
| 96 | } |
| 97 | b = append(b, value...) |
| 98 | } |
| 99 | b = append(b, '}') |
Marcel van Lohuizen | 865f159 | 2019-07-02 19:43:45 +0200 | [diff] [blame] | 100 | return b, err |
Marcel van Lohuizen | f4d483e | 2019-05-20 08:03:10 -0400 | [diff] [blame] | 101 | } |