aboutsummaryrefslogtreecommitdiff
path: root/container/smap.go
blob: 688ec4023abfeee8dcfe1d7dd5205795e25f42f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package container

import (
	"slices"
	"sync"
)

// M is ordered and concurent safe map implementation.
type M[K comparable, V any] struct {
	m  map[K]V
	k  []K
	mu sync.RWMutex
}

// Make returns new instance with `capacity` initial capacity.
func Make[K comparable, V any](capacity int) M[K, V] {
	return M[K, V]{
		m: make(map[K]V, capacity),
		k: make([]K, 0, capacity),
	}
}

// Get value `V` by key `k K`. Returns zero value if the key is absent.
func (m *M[K, V]) Get(k K) V {
	m.mu.RLock()
	defer m.mu.RUnlock()

	return m.m[k]
}

// Get2 value `v V` by key `k K` and a presence flag `ok bool`. Returns
// `(value, true)` if the key exists, and `(zero value, false)` if the key is
// absent.
func (m *M[K, V]) Get2(k K) (v V, ok bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	v, ok = m.m[k]

	return v, ok
}

// Has returns true if key `k K` exists in map.
func (m *M[K, V]) Has(k K) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()

	_, ok := m.m[k]

	return ok
}

// Set value `v V` to key `k K`.
func (m *M[K, V]) Set(k K, v V) {
	m.mu.Lock()
	defer m.mu.Unlock()

	if _, exists := m.m[k]; !exists {
		m.k = append(m.k, k)
	}

	m.m[k] = v
}

// Delete key `k K` from map.
func (m *M[K, V]) Delete(k K) {
	m.mu.Lock()
	defer m.mu.Unlock()

	if _, ok := m.m[k]; !ok {
		return
	}

	idx := slices.Index(m.k, k)
	m.k = slices.Delete(m.k, idx, idx+1)

	delete(m.m, k)
}

// Keys is iterator over keys.
func (m *M[K, V]) Keys(yield func(K) bool) {
	for _, k := range m.k {
		if !yield(k) {
			break
		}
	}
}

// Values is iterator over values.
func (m *M[K, V]) Values(yield func(V) bool) {
	for _, k := range m.k {
		if !yield(m.m[k]) {
			break
		}
	}
}

// Entries is iterator over key:value pairs.
func (m *M[K, V]) Entries(yield func(K, V) bool) {
	for _, k := range m.k {
		if !yield(k, m.m[k]) {
			break
		}
	}
}