func Drop() Rule {
	return Rule(nil).ThenDrop()
}
/* TODO(jdef) not sure that this is very useful, leaving out for now...

EveryN invokes the receiving rule beginning with the first event seen and then every n'th
time after that. If nthTime is less then 2 then the receiver is returned, undecorated.
The "otherwise" Rule (may be null) is invoked for every event in between the n'th invocations.
A cancelled context will trigger the "otherwise" rule.
func (r Rule) EveryN(nthTime int, otherwise Rule) Rule {
if nthTime < 2 || r == nil {
return r
}
return limit(r, acquireEveryN(nthTime), OverflowOtherwise, otherwise)
}

acquireEveryN returns an "acquire" func (for use w/ rate-limiting) that returns true every N'th invocation.
the returned func MUST NOT be used with a potentially blocking Overflow policy (or else it panics).
nthTime SHOULD be greater than math.MinInt32, values less than 2 probably don't make sense in practice.
func acquireEveryN(nthTime int) func(context.Context, bool) bool {
var (
i       = 1 // begin with the first event seen
m       sync.Mutex
)
return func(ctx context.Context, block bool) (result bool) {
if block {
panic("acquireEveryN should never be asked to block")
}
select {
case <-ctx.Done():
default:
m.Lock()
i--
if i <= 0 {
i = nthTime
result = true
}
m.Unlock()
}
return
}
}


Drop aborts the Chain and returns the (context.Context, *scheduler.Call, error) tuple as-is.
package callrules
import (
	"context"
	"fmt"
	"sync"
	"github.com/mesos/mesos-go/api/v1/lib"
	"github.com/mesos/mesos-go/api/v1/lib/scheduler"
)
type (
	evaler interface {
		Eval(context.Context, *scheduler.Call, mesos.Response, error, Chain) (context.Context, *scheduler.Call, mesos.Response, error)
	}
	Rule func(context.Context, *scheduler.Call, mesos.Response, error, Chain) (context.Context, *scheduler.Call, mesos.Response, error)
	Chain func(context.Context, *scheduler.Call, mesos.Response, error) (context.Context, *scheduler.Call, mesos.Response, error)
	Rules []Rule
	ErrorList []error
)
var (
	_ = evaler(Rule(nil))
	_ = evaler(Rules{})
)
func ChainIdentity(ctx context.Context, e *scheduler.Call, z mesos.Response, err error) (context.Context, *scheduler.Call, mesos.Response, error) {
	return ctx, e, z, err
}
func (r Rule) Eval(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) {
	if r != nil {
		return r(ctx, e, z, err, ch)
	}
	return ch(ctx, e, z, err)
}
func (rs Rules) Eval(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) {
	return ch(rs.Chain()(ctx, e, z, err))
}
func (rs Rules) Chain() Chain {
	if len(rs) == 0 {
		return ChainIdentity
	}
	return func(ctx context.Context, e *scheduler.Call, z mesos.Response, err error) (context.Context, *scheduler.Call, mesos.Response, error) {
		return rs[0].Eval(ctx, e, z, err, rs[1:].Chain())
	}
}
func New(rs ...Rule) Rule { return Rules(rs).Eval }
const msgNoErrors = "no errors"
func (es ErrorList) Error() string {
	switch len(es) {
	case 0:
		return msgNoErrors
	case 1:
		return es[0].Error()
	default:
		return fmt.Sprintf("%s (and %d more errors)", es[0], len(es)-1)
	}
}
func Error2(a, b error) error {
	if a == nil {
		if b == nil {
			return nil
		}
		if list, ok := b.(ErrorList); ok {
			return flatten(list).Err()
		}
		return b
	}
	if b == nil {
		if list, ok := a.(ErrorList); ok {
			return flatten(list).Err()
		}
		return a
	}
	return Error(a, b)
}
func (es ErrorList) Err() error {
	switch len(es) {
	case 0:
		return nil
	case 1:
		return es[0]
	default:
		return es
	}
}
func IsErrorList(err error) bool {
	if err != nil {
		_, ok := err.(ErrorList)
		return ok
	}
	return false
}
func Error(es ...error) error {
	return flatten(es).Err()
}
func flatten(errors []error) ErrorList {
	if errors == nil || len(errors) == 0 {
		return nil
	}
	result := make([]error, 0, len(errors))
	for _, err := range errors {
		if err != nil {
			if multi, ok := err.(ErrorList); ok {
				result = append(result, flatten(multi)...)
			} else {
				result = append(result, err)
			}
		}
	}
	return ErrorList(result)
}
func (r Rule) If(b bool) Rule {
	if b {
		return r
	}
	return nil
}
func (r Rule) Unless(b bool) Rule {
	if !b {
		return r
	}
	return nil
}
func (r Rule) Once() Rule {
	if r == nil {
		return nil
	}
	var once sync.Once
	return func(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) {
		ruleInvoked := false
		once.Do(func() {
			ctx, e, z, err = r(ctx, e, z, err, ch)
			ruleInvoked = true
		})
		if !ruleInvoked {
			ctx, e, z, err = ch(ctx, e, z, err)
		}
		return ctx, e, z, err
	}
}
func (r Rule) UnlessDone() Rule {
	if r == nil {
		return nil
	}
	return func(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) {
		select {
		case <-ctx.Done():
			return ctx, e, z, Error2(err, ctx.Err())
		default:
			return r(ctx, e, z, err, ch)
		}
	}
}
type Overflow int
const (
	OverflowWait Overflow = iota
	OverflowOtherwise
)
func (r Rule) RateLimit(p <-chan struct{}, over Overflow, otherwise Rule) Rule {
	return limit(r, acquireChan(p), over, otherwise)
}
func acquireChan(tokenCh <-chan struct{}) func(context.Context, bool) bool {
	if tokenCh == nil {
		return func(ctx context.Context, block bool) bool {
			if block {
				select {
				case <-ctx.Done():
				default:
					panic("deadlock detected: block should never be true when the token chan is nil")
				}
			}
			return false
		}
	}
	return func(ctx context.Context, block bool) bool {
		if block {
			select {
			case <-tokenCh:
				select {
				case <-ctx.Done():
				default:
					return true
				}
			case <-ctx.Done():
			}
			return false
		}
		select {
		case <-tokenCh:
			return true
		default:
			return false
		}
	}
}
func limit(r Rule, acquire func(_ context.Context, block bool) bool, over Overflow, otherwise Rule) Rule {
	if r == nil {
		return nil
	}
	if acquire == nil {
		panic("acquire func is not allowed to be nil")
	}
	blocking := false
	switch over {
	case OverflowOtherwise:
	case OverflowWait:
		blocking = true
	default:
		panic(fmt.Sprintf("unexpected Overflow type: %#v", over))
	}
	return func(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) {
		if !acquire(ctx, blocking) {
			return otherwise.Eval(ctx, e, z, err, ch)
		}
		return r(ctx, e, z, err, ch)
	}
}