func (msm *MultistreamMuxer) AddHandlerWithFunc(protocol string, match func(string) bool, handler HandlerFunc) {
	msm.handlerlock.Lock()
	defer msm.handlerlock.Unlock()
	msm.removeHandler(protocol)
	msm.handlers = append(msm.handlers, Handler{
		MatchFunc: match,
		Handle:    handler,
		AddName:   protocol,
	})
}
AddHandlerWithFunc attaches a new protocol handler to the muxer with a match.
If the match function returns true for a given protocol tag, the protocol
will be selected even if the handler name and protocol tags are different.
package multistream
import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"sync"
	"github.com/multiformats/go-varint"
)
var ErrTooLarge = errors.New("incoming message was too large")
const ProtocolID = "/multistream/1.0.0"
var writerPool = sync.Pool{
	New: func() interface{} {
		return bufio.NewWriter(nil)
	},
}
type HandlerFunc = func(protocol string, rwc io.ReadWriteCloser) error
type Handler struct {
	MatchFunc func(string) bool
	Handle    HandlerFunc
	AddName   string
}
type MultistreamMuxer struct {
	handlerlock sync.RWMutex
	handlers    []Handler
}
func NewMultistreamMuxer() *MultistreamMuxer {
	return new(MultistreamMuxer)
}
type LazyConn interface {
	io.ReadWriteCloser
	Flush() error
}
func writeUvarint(w io.Writer, i uint64) error {
	varintbuf := make([]byte, 16)
	n := varint.PutUvarint(varintbuf, i)
	_, err := w.Write(varintbuf[:n])
	if err != nil {
		return err
	}
	return nil
}
func delimWriteBuffered(w io.Writer, mes []byte) error {
	bw := getWriter(w)
	defer putWriter(bw)
	err := delimWrite(bw, mes)
	if err != nil {
		return err
	}
	return bw.Flush()
}
func delitmWriteAll(w io.Writer, messages ...[]byte) error {
	for _, mes := range messages {
		if err := delimWrite(w, mes); err != nil {
			return fmt.Errorf("failed to write messages %s, err: %v	", string(mes), err)
		}
	}
	return nil
}
func delimWrite(w io.Writer, mes []byte) error {
	err := writeUvarint(w, uint64(len(mes)+1))
	if err != nil {
		return err
	}
	_, err = w.Write(mes)
	if err != nil {
		return err
	}
	_, err = w.Write([]byte{'\n'})
	if err != nil {
		return err
	}
	return nil
}
func Ls(rw io.ReadWriter) ([]string, error) {
	err := handshake(rw)
	if err != nil {
		return nil, err
	}
	err = delimWriteBuffered(rw, []byte("ls"))
	if err != nil {
		return nil, err
	}
	response, err := lpReadBuf(rw)
	if err != nil {
		return nil, err
	}
	r := bytes.NewReader(response)
	var out []string
	for {
		val, err := lpReadBuf(r)
		switch err {
		default:
			return nil, err
		case io.EOF:
			return out, nil
		case nil:
			out = append(out, string(val))
		}
	}
}
func fulltextMatch(s string) func(string) bool {
	return func(a string) bool {
		return a == s
	}
}
func (msm *MultistreamMuxer) AddHandler(protocol string, handler HandlerFunc) {
	msm.AddHandlerWithFunc(protocol, fulltextMatch(protocol), handler)
}