Create UIDStore package

This package can be used to provide a source for mapping mock UIDs back
to relevant keys for alternate backends. For example, for the Maildir
backend, we need to map between UID and message file names.
This commit is contained in:
Ben Burwell 2019-07-11 09:44:50 -04:00 committed by Drew DeVault
parent 3b09c07e7a
commit d7cd35e72b
1 changed files with 62 additions and 0 deletions

62
lib/uidstore/uidstore.go Normal file
View File

@ -0,0 +1,62 @@
// Package uidstore provides a concurrency-safe two-way mapping between UIDs
// used by the UI and arbitrary string keys as used by different mail backends.
//
// Multiple Store instances can safely be created and the UIDs that they
// generate will be globally unique.
package uidstore
import (
"sync"
"sync/atomic"
)
var nextUID uint32 = 1
// Store holds a mapping between application keys and globally-unique UIDs.
type Store struct {
keyByUID map[uint32]string
uidByKey map[string]uint32
m sync.Mutex
}
// NewStore creates a new, empty Store.
func NewStore() *Store {
return &Store{
keyByUID: make(map[uint32]string),
uidByKey: make(map[string]uint32),
}
}
// GetOrInsert returns the UID for the provided key. If the key was already
// present in the store, the same UID value is returned. Otherwise, the key is
// inserted and the newly generated UID is returned.
func (s *Store) GetOrInsert(key string) uint32 {
s.m.Lock()
defer s.m.Unlock()
if uid, ok := s.uidByKey[key]; ok {
return uid
}
uid := atomic.AddUint32(&nextUID, 1)
s.keyByUID[uid] = key
s.uidByKey[key] = uid
return uid
}
// GetKey returns the key for the provided UID, if available.
func (s *Store) GetKey(uid uint32) (string, bool) {
s.m.Lock()
defer s.m.Unlock()
key, ok := s.keyByUID[uid]
return key, ok
}
// RemoveUID removes the specified UID from the store.
func (s *Store) RemoveUID(uid uint32) {
s.m.Lock()
defer s.m.Unlock()
key, ok := s.keyByUID[uid]
if ok {
delete(s.uidByKey, key)
}
delete(s.keyByUID, uid)
}