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 /lib/uidstore | |
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.
Diffstat (limited to 'lib/uidstore')
-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) +} |