git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/orderedmap/orderedmap.go (about)

     1  package orderedmap
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"sort"
     7  )
     8  
     9  type Element[K comparable, V any] struct {
    10  	Key   K
    11  	Value V
    12  }
    13  
    14  // Map is wrapper for map that keeps it's order when deserializing from JSON
    15  // Warning: it's highly inneficient and should only be used for configuration file or similar use cases
    16  type Map[K comparable, V any] struct {
    17  	elems []Element[K, V]
    18  	data  map[K]V
    19  }
    20  
    21  func (m *Map[K, V]) UnmarshalJSON(data []byte) error {
    22  	json.Unmarshal(data, &m.data)
    23  
    24  	m.elems = make([]Element[K, V], 0, len(m.data))
    25  
    26  	index := make(map[K]int)
    27  	for key, value := range m.data {
    28  		m.elems = append(m.elems, Element[K, V]{Key: key, Value: value})
    29  		esc, _ := json.Marshal(key) //Escape the key
    30  		index[key] = bytes.Index(data, esc)
    31  	}
    32  
    33  	sort.Slice(m.elems, func(i, j int) bool { return index[m.elems[i].Key] < index[m.elems[j].Key] })
    34  	return nil
    35  }
    36  
    37  func (m *Map[K, V]) Elems() []Element[K, V] {
    38  	return m.elems
    39  }