Files
crockery/vendor/github.com/emersion/go-imap/handle.go
2018-03-05 12:19:04 +00:00

122 lines
2.1 KiB
Go

package imap
import (
"sync"
)
// A response that can be either accepted or rejected by a handler.
type RespHandle struct {
Resp interface{}
Accepts chan bool
}
// Accept this response. This means that the handler will process it.
func (h *RespHandle) Accept() {
h.Accepts <- true
}
// Reject this response. The handler cannot process it.
func (h *RespHandle) Reject() {
h.Accepts <- false
}
// Accept this response if it has the specified name. If not, reject it.
func (h *RespHandle) AcceptNamedResp(name string) (fields []interface{}, accepted bool) {
res, ok := h.Resp.(*Resp)
if !ok || len(res.Fields) == 0 {
h.Reject()
return
}
n, ok := res.Fields[0].(string)
if !ok || n != name {
h.Reject()
return
}
h.Accept()
fields = res.Fields[1:]
accepted = true
return
}
// Delivers responses to handlers.
type RespHandler chan *RespHandle
// Handles responses from a handler.
type RespHandlerFrom interface {
HandleFrom(hdlr RespHandler) error
}
// A RespHandlerFrom that forwards responses to multiple RespHandler.
type MultiRespHandler struct {
handlers []RespHandler
locker sync.Locker
}
func NewMultiRespHandler() *MultiRespHandler {
return &MultiRespHandler{
locker: &sync.Mutex{},
}
}
func (mh *MultiRespHandler) HandleFrom(ch RespHandler) error {
for rh := range ch {
mh.locker.Lock()
accepted := false
for i := len(mh.handlers) - 1; i >= 0; i-- {
hdlr := mh.handlers[i]
rh := &RespHandle{
Resp: rh.Resp,
Accepts: make(chan bool),
}
hdlr <- rh
if accepted = <-rh.Accepts; accepted {
break
}
}
mh.locker.Unlock()
if accepted {
rh.Accept()
} else {
rh.Reject()
}
}
mh.locker.Lock()
for _, hdlr := range mh.handlers {
close(hdlr)
}
mh.handlers = nil
mh.locker.Unlock()
return nil
}
func (mh *MultiRespHandler) Add(hdlr RespHandler) {
if hdlr == nil {
return
}
mh.locker.Lock()
mh.handlers = append(mh.handlers, hdlr)
mh.locker.Unlock()
}
func (mh *MultiRespHandler) Del(hdlr RespHandler) {
mh.locker.Lock()
for i, h := range mh.handlers {
if h == hdlr {
close(hdlr)
mh.handlers = append(mh.handlers[:i], mh.handlers[i+1:]...)
}
}
mh.locker.Unlock()
}