github.com/MetalBlockchain/metalgo@v1.11.9/utils/bimap/bimap.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package bimap
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"errors"
    10  
    11  	"golang.org/x/exp/maps"
    12  
    13  	"github.com/MetalBlockchain/metalgo/utils"
    14  )
    15  
    16  var (
    17  	_ json.Marshaler   = (*BiMap[int, int])(nil)
    18  	_ json.Unmarshaler = (*BiMap[int, int])(nil)
    19  
    20  	nullBytes       = []byte("null")
    21  	errNotBijective = errors.New("map not bijective")
    22  )
    23  
    24  type Entry[K, V any] struct {
    25  	Key   K
    26  	Value V
    27  }
    28  
    29  // BiMap is a bi-directional map.
    30  type BiMap[K, V comparable] struct {
    31  	keyToValue map[K]V
    32  	valueToKey map[V]K
    33  }
    34  
    35  // New creates a new empty bimap.
    36  func New[K, V comparable]() *BiMap[K, V] {
    37  	return &BiMap[K, V]{
    38  		keyToValue: make(map[K]V),
    39  		valueToKey: make(map[V]K),
    40  	}
    41  }
    42  
    43  // Put the key value pair into the map. If either [key] or [val] was previously
    44  // in the map, the previous entries will be removed and returned.
    45  //
    46  // Note: Unlike normal maps, it's possible that Put removes 0, 1, or 2 existing
    47  // entries to ensure that mappings are one-to-one.
    48  func (m *BiMap[K, V]) Put(key K, val V) []Entry[K, V] {
    49  	var removed []Entry[K, V]
    50  	oldVal, oldValDeleted := m.DeleteKey(key)
    51  	if oldValDeleted {
    52  		removed = append(removed, Entry[K, V]{
    53  			Key:   key,
    54  			Value: oldVal,
    55  		})
    56  	}
    57  	oldKey, oldKeyDeleted := m.DeleteValue(val)
    58  	if oldKeyDeleted {
    59  		removed = append(removed, Entry[K, V]{
    60  			Key:   oldKey,
    61  			Value: val,
    62  		})
    63  	}
    64  	m.keyToValue[key] = val
    65  	m.valueToKey[val] = key
    66  	return removed
    67  }
    68  
    69  // GetKey that maps to the provided value.
    70  func (m *BiMap[K, V]) GetKey(val V) (K, bool) {
    71  	key, ok := m.valueToKey[val]
    72  	return key, ok
    73  }
    74  
    75  // GetValue that is mapped to the provided key.
    76  func (m *BiMap[K, V]) GetValue(key K) (V, bool) {
    77  	val, ok := m.keyToValue[key]
    78  	return val, ok
    79  }
    80  
    81  // HasKey returns true if [key] is in the map.
    82  func (m *BiMap[K, _]) HasKey(key K) bool {
    83  	_, ok := m.keyToValue[key]
    84  	return ok
    85  }
    86  
    87  // HasValue returns true if [val] is in the map.
    88  func (m *BiMap[_, V]) HasValue(val V) bool {
    89  	_, ok := m.valueToKey[val]
    90  	return ok
    91  }
    92  
    93  // DeleteKey removes [key] from the map and returns the value it mapped to.
    94  func (m *BiMap[K, V]) DeleteKey(key K) (V, bool) {
    95  	val, ok := m.keyToValue[key]
    96  	if !ok {
    97  		return utils.Zero[V](), false
    98  	}
    99  	delete(m.keyToValue, key)
   100  	delete(m.valueToKey, val)
   101  	return val, true
   102  }
   103  
   104  // DeleteValue removes [val] from the map and returns the key that mapped to it.
   105  func (m *BiMap[K, V]) DeleteValue(val V) (K, bool) {
   106  	key, ok := m.valueToKey[val]
   107  	if !ok {
   108  		return utils.Zero[K](), false
   109  	}
   110  	delete(m.keyToValue, key)
   111  	delete(m.valueToKey, val)
   112  	return key, true
   113  }
   114  
   115  // Keys returns the keys of the map. The keys will be in an indeterminate order.
   116  func (m *BiMap[K, _]) Keys() []K {
   117  	return maps.Keys(m.keyToValue)
   118  }
   119  
   120  // Values returns the values of the map. The values will be in an indeterminate
   121  // order.
   122  func (m *BiMap[_, V]) Values() []V {
   123  	return maps.Values(m.keyToValue)
   124  }
   125  
   126  // Len return the number of entries in this map.
   127  func (m *BiMap[K, V]) Len() int {
   128  	return len(m.keyToValue)
   129  }
   130  
   131  func (m *BiMap[K, V]) MarshalJSON() ([]byte, error) {
   132  	return json.Marshal(m.keyToValue)
   133  }
   134  
   135  func (m *BiMap[K, V]) UnmarshalJSON(b []byte) error {
   136  	if bytes.Equal(b, nullBytes) {
   137  		return nil
   138  	}
   139  	var keyToValue map[K]V
   140  	if err := json.Unmarshal(b, &keyToValue); err != nil {
   141  		return err
   142  	}
   143  	valueToKey := make(map[V]K, len(keyToValue))
   144  	for k, v := range keyToValue {
   145  		valueToKey[v] = k
   146  	}
   147  	if len(keyToValue) != len(valueToKey) {
   148  		return errNotBijective
   149  	}
   150  
   151  	m.keyToValue = keyToValue
   152  	m.valueToKey = valueToKey
   153  	return nil
   154  }