mirror of
https://github.com/lukaszraczylo/go-simple-graphql.git
synced 2026-10-12 00:45:31 +00:00
In high frequency environment the allegro bigcache caused significant memory usage overhead. This commit replaces it with something much lighter.
122 lines
2.1 KiB
Go
122 lines
2.1 KiB
Go
package ordered_map
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
)
|
|
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
|
|
type OrderedMap struct {
|
|
values map[string]interface{}
|
|
keys []string
|
|
}
|
|
|
|
func New() *OrderedMap {
|
|
o := OrderedMap{}
|
|
o.keys = []string{}
|
|
o.values = map[string]interface{}{}
|
|
return &o
|
|
}
|
|
|
|
func (o *OrderedMap) Set(key string, value interface{}) {
|
|
_, exists := o.values[key]
|
|
if !exists {
|
|
o.keys = append(o.keys, key)
|
|
}
|
|
o.values[key] = value
|
|
}
|
|
|
|
func (o OrderedMap) MarshalJSON() ([]byte, error) {
|
|
var buf bytes.Buffer
|
|
buf.WriteByte('{')
|
|
encoder := json.NewEncoder(&buf)
|
|
encoder.SetEscapeHTML(false)
|
|
encoder.SetIndent("", "")
|
|
for i, k := range o.keys {
|
|
if i > 0 {
|
|
buf.WriteByte(',')
|
|
}
|
|
buf.WriteByte('"')
|
|
buf.WriteString(k)
|
|
buf.WriteString(`":`)
|
|
customEncoder := &customJsonEncoder{buf: &buf}
|
|
if err := customEncoder.Encode(o.values[k]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
buf.WriteByte('}')
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
type customJsonEncoder struct {
|
|
buf *bytes.Buffer
|
|
}
|
|
|
|
func (e *customJsonEncoder) Encode(v interface{}) error {
|
|
if v == nil {
|
|
e.buf.WriteString("null")
|
|
return nil
|
|
}
|
|
|
|
switch val := v.(type) {
|
|
case *OrderedMap:
|
|
data, err := json.Marshal(val.values)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
e.buf.Write(data)
|
|
default:
|
|
data, err := json.Marshal(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
e.buf.Write(data)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o OrderedMap) Keys() []string {
|
|
return o.keys
|
|
}
|
|
|
|
func (o OrderedMap) Values() []interface{} {
|
|
var values []interface{}
|
|
for _, k := range o.keys {
|
|
values = append(values, o.values[k])
|
|
}
|
|
return values
|
|
}
|
|
|
|
func (o *OrderedMap) Delete(key string) {
|
|
delete(o.values, key)
|
|
for i, k := range o.keys {
|
|
if k == key {
|
|
o.keys = append(o.keys[:i], o.keys[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func (o OrderedMap) Exists(key string) bool {
|
|
_, exists := o.values[key]
|
|
return exists
|
|
}
|
|
|
|
func (o *OrderedMap) UnmarshalJSON(data []byte) error {
|
|
var values map[string]interface{}
|
|
err := json.Unmarshal(data, &values)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
o.keys = []string{}
|
|
o.values = map[string]interface{}{}
|
|
for k, v := range values {
|
|
o.Set(k, v)
|
|
}
|
|
|
|
return nil
|
|
}
|