2022-06-20 21:49:05 +02:00
|
|
|
package imap
|
|
|
|
|
2022-07-24 17:13:43 +02:00
|
|
|
import (
|
2022-08-01 19:18:25 +02:00
|
|
|
"sort"
|
2022-07-24 17:13:43 +02:00
|
|
|
"sync"
|
|
|
|
)
|
2022-06-20 21:49:05 +02:00
|
|
|
|
|
|
|
type SeqMap struct {
|
|
|
|
lock sync.Mutex
|
|
|
|
// map of IMAP sequence numbers to message UIDs
|
2022-08-01 19:18:25 +02:00
|
|
|
m []uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize sets the initial seqmap of the mailbox
|
|
|
|
func (s *SeqMap) Initialize(uids []uint32) {
|
|
|
|
s.lock.Lock()
|
2022-08-16 19:25:48 +02:00
|
|
|
s.m = make([]uint32, len(uids))
|
|
|
|
copy(s.m, uids)
|
2022-08-01 19:18:25 +02:00
|
|
|
s.sort()
|
|
|
|
s.lock.Unlock()
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SeqMap) Size() int {
|
|
|
|
s.lock.Lock()
|
|
|
|
size := len(s.m)
|
|
|
|
s.lock.Unlock()
|
|
|
|
return size
|
|
|
|
}
|
|
|
|
|
2022-08-01 19:18:25 +02:00
|
|
|
// Get returns the UID of the given seqnum
|
2022-06-20 21:49:05 +02:00
|
|
|
func (s *SeqMap) Get(seqnum uint32) (uint32, bool) {
|
2022-08-01 19:18:25 +02:00
|
|
|
if int(seqnum) > s.Size() || seqnum < 1 {
|
|
|
|
return 0, false
|
|
|
|
}
|
2022-06-20 21:49:05 +02:00
|
|
|
s.lock.Lock()
|
2022-08-01 19:18:25 +02:00
|
|
|
uid := s.m[seqnum-1]
|
2022-06-20 21:49:05 +02:00
|
|
|
s.lock.Unlock()
|
2022-08-01 19:18:25 +02:00
|
|
|
return uid, true
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|
|
|
|
|
2022-08-01 19:18:25 +02:00
|
|
|
// Put adds a UID to the slice. Put should only be used to add new messages
|
|
|
|
// into the slice
|
|
|
|
func (s *SeqMap) Put(uid uint32) {
|
2022-06-20 21:49:05 +02:00
|
|
|
s.lock.Lock()
|
2022-08-01 19:18:25 +02:00
|
|
|
for _, n := range s.m {
|
|
|
|
if n == uid {
|
|
|
|
// We already have this UID, don't insert it.
|
|
|
|
s.lock.Unlock()
|
|
|
|
return
|
|
|
|
}
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|
2022-08-01 19:18:25 +02:00
|
|
|
s.m = append(s.m, uid)
|
|
|
|
s.sort()
|
2022-06-20 21:49:05 +02:00
|
|
|
s.lock.Unlock()
|
|
|
|
}
|
|
|
|
|
2022-08-01 19:18:25 +02:00
|
|
|
// Pop removes seqnum from the SeqMap. seqnum must be a valid seqnum, ie
|
|
|
|
// [1:size of mailbox]
|
2022-06-20 21:49:05 +02:00
|
|
|
func (s *SeqMap) Pop(seqnum uint32) (uint32, bool) {
|
2022-08-01 19:18:25 +02:00
|
|
|
if int(seqnum) > s.Size() || seqnum < 1 {
|
|
|
|
return 0, false
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|
2022-08-01 19:18:25 +02:00
|
|
|
s.lock.Lock()
|
|
|
|
uid := s.m[seqnum-1]
|
|
|
|
s.m = append(s.m[:seqnum-1], s.m[seqnum:]...)
|
2022-06-20 21:49:05 +02:00
|
|
|
s.lock.Unlock()
|
2022-08-01 19:18:25 +02:00
|
|
|
return uid, true
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|
|
|
|
|
2022-08-01 19:18:25 +02:00
|
|
|
// sort sorts the slice in ascending UID order. See:
|
|
|
|
// https://datatracker.ietf.org/doc/html/rfc3501#section-2.3.1.2
|
|
|
|
func (s *SeqMap) sort() {
|
|
|
|
// Always be sure the SeqMap is sorted
|
|
|
|
sort.Slice(s.m, func(i, j int) bool {
|
|
|
|
return s.m[i] < s.m[j]
|
|
|
|
})
|
2022-06-20 21:49:05 +02:00
|
|
|
}
|