95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
// Package orderedmap provides a generic ordered map that maintains insertion order.
|
|
// It wraps github.com/wk8/go-ordered-map/v2 to encapsulate the dependency.
|
|
package orderedmap
|
|
|
|
import (
|
|
"encoding/json"
|
|
"iter"
|
|
|
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
|
)
|
|
|
|
// Map is a generic ordered map that maintains insertion order.
|
|
type Map[K comparable, V any] struct {
|
|
om *orderedmap.OrderedMap[K, V]
|
|
}
|
|
|
|
// New creates a new empty ordered map.
|
|
func New[K comparable, V any]() *Map[K, V] {
|
|
return &Map[K, V]{
|
|
om: orderedmap.New[K, V](),
|
|
}
|
|
}
|
|
|
|
// Get retrieves a value by key.
|
|
func (m *Map[K, V]) Get(key K) (V, bool) {
|
|
if m == nil || m.om == nil {
|
|
var zero V
|
|
return zero, false
|
|
}
|
|
return m.om.Get(key)
|
|
}
|
|
|
|
// Set sets a key-value pair. If the key already exists, its value is updated
|
|
// but its position in the iteration order is preserved. If the key is new,
|
|
// it is appended to the end.
|
|
func (m *Map[K, V]) Set(key K, value V) {
|
|
if m == nil {
|
|
return
|
|
}
|
|
if m.om == nil {
|
|
m.om = orderedmap.New[K, V]()
|
|
}
|
|
m.om.Set(key, value)
|
|
}
|
|
|
|
// Len returns the number of entries.
|
|
func (m *Map[K, V]) Len() int {
|
|
if m == nil || m.om == nil {
|
|
return 0
|
|
}
|
|
return m.om.Len()
|
|
}
|
|
|
|
// All returns an iterator over all key-value pairs in insertion order.
|
|
func (m *Map[K, V]) All() iter.Seq2[K, V] {
|
|
return func(yield func(K, V) bool) {
|
|
if m == nil || m.om == nil {
|
|
return
|
|
}
|
|
for pair := m.om.Oldest(); pair != nil; pair = pair.Next() {
|
|
if !yield(pair.Key, pair.Value) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ToMap converts to a regular Go map.
|
|
// Note: The resulting map does not preserve order.
|
|
func (m *Map[K, V]) ToMap() map[K]V {
|
|
if m == nil || m.om == nil {
|
|
return nil
|
|
}
|
|
result := make(map[K]V, m.om.Len())
|
|
for pair := m.om.Oldest(); pair != nil; pair = pair.Next() {
|
|
result[pair.Key] = pair.Value
|
|
}
|
|
return result
|
|
}
|
|
|
|
// MarshalJSON implements json.Marshaler. The JSON output preserves key order.
|
|
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
|
|
if m == nil || m.om == nil {
|
|
return []byte("null"), nil
|
|
}
|
|
return json.Marshal(m.om)
|
|
}
|
|
|
|
// UnmarshalJSON implements json.Unmarshaler. The insertion order matches the
|
|
// order of keys in the JSON input.
|
|
func (m *Map[K, V]) UnmarshalJSON(data []byte) error {
|
|
m.om = orderedmap.New[K, V]()
|
|
return json.Unmarshal(data, &m.om)
|
|
}
|