diff options
author | Ben Burwell <ben@benburwell.com> | 2019-07-11 09:44:50 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-07-12 11:09:47 -0400 |
commit | d7cd35e72b81644774e5f1ab44ff8645e31aa510 (patch) | |
tree | c768fd6d1547d873d86210a85045e29f6c36c9cb | |
parent | 3b09c07e7a75feed8a9086b0a9003c2cf3ffea59 (diff) |
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.
-rw-r--r-- | lib/uidstore/uidstore.go | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/uidstore/uidstore.go b/lib/uidstore/uidstore.go new file mode 100644 index 0000000..11c5e47 --- /dev/null +++ b/lib/uidstore/uidstore.go @@ -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) +} |