func ReadNextToken(r io.Reader) (string, error) {
	tok, err := ReadNextTokenBytes(r)
	if err != nil {
		return "", err
	}
	return string(tok), nil
}
ReadNextToken extracts a token from a Reader. It is used during
protocol negotiation and returns a string.
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)
}
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,
	})
}
func (msm *MultistreamMuxer) RemoveHandler(protocol string) {
	msm.handlerlock.Lock()
	defer msm.handlerlock.Unlock()
	msm.removeHandler(protocol)
}
func (msm *MultistreamMuxer) removeHandler(protocol string) {
	for i, h := range msm.handlers {
		if h.AddName == protocol {
			msm.handlers = append(msm.handlers[:i], msm.handlers[i+1:]...)
			return
		}
	}
}
func (msm *MultistreamMuxer) Protocols() []string {
	msm.handlerlock.RLock()
	defer msm.handlerlock.RUnlock()
	var out []string
	for _, h := range msm.handlers {
		out = append(out, h.AddName)
	}
	return out
}
var ErrIncorrectVersion = errors.New("client connected with incorrect version")
func (msm *MultistreamMuxer) findHandler(proto string) *Handler {
	msm.handlerlock.RLock()
	defer msm.handlerlock.RUnlock()
	for _, h := range msm.handlers {
		if h.MatchFunc(proto) {
			return &h
		}
	}
	return nil
}
func (msm *MultistreamMuxer) NegotiateLazy(rwc io.ReadWriteCloser) (io.ReadWriteCloser, string, HandlerFunc, error) {
	pval := make(chan string, 1)
	writeErr := make(chan error, 1)
	defer close(pval)
	lzc := &lazyServerConn{
		con: rwc,
	}
	started := make(chan struct{})
	go lzc.waitForHandshake.Do(func() {
		close(started)
		defer close(writeErr)
		if err := delimWriteBuffered(rwc, []byte(ProtocolID)); err != nil {
			lzc.werr = err
			writeErr <- err
			return
		}
		for proto := range pval {
			if err := delimWriteBuffered(rwc, []byte(proto)); err != nil {
				lzc.werr = err
				writeErr <- err
				return
			}
		}
	})
	<-started
	line, err := ReadNextToken(rwc)
	if err != nil {
		return nil, "", nil, err
	}
	if line != ProtocolID {
		rwc.Close()
		return nil, "", nil, ErrIncorrectVersion
	}
loop:
	for {
		tok, err := ReadNextToken(rwc)
		if err != nil {
			rwc.Close()
			return nil, "", nil, err
		}
		switch tok {
		case "ls":
			protos, err := msm.encodeLocalProtocols()
			if err != nil {
				rwc.Close()
				return nil, "", nil, err
			}
			select {
			case pval <- string(protos):
			case err := <-writeErr:
				rwc.Close()
				return nil, "", nil, err
			}
		default:
			h := msm.findHandler(tok)
			if h == nil {
				select {
				case pval <- "na":
				case err := <-writeErr:
					rwc.Close()
					return nil, "", nil, err
				}
				continue loop
			}
			select {
			case pval <- tok:
			case <-writeErr:
			}
			return lzc, tok, h.Handle, nil
		}
	}
}
func (msm *MultistreamMuxer) Negotiate(rwc io.ReadWriteCloser) (string, HandlerFunc, error) {
	err := delimWriteBuffered(rwc, []byte(ProtocolID))
	if err != nil {
		return "", nil, err
	}
	line, err := ReadNextToken(rwc)
	if err != nil {
		return "", nil, err
	}
	if line != ProtocolID {
		rwc.Close()
		return "", nil, ErrIncorrectVersion
	}
loop:
	for {
		tok, err := ReadNextToken(rwc)
		if err != nil {
			return "", nil, err
		}
		switch tok {
		case "ls":
			err := msm.Ls(rwc)
			if err != nil {
				return "", nil, err
			}
		default:
			h := msm.findHandler(tok)
			if h == nil {
				err := delimWriteBuffered(rwc, []byte("na"))
				if err != nil {
					return "", nil, err
				}
				continue loop
			}
			err := delimWriteBuffered(rwc, []byte(tok))
			if err != nil {
				return "", nil, err
			}
			return tok, h.Handle, nil
		}
	}
}
func (msm *MultistreamMuxer) Ls(w io.Writer) error {
	protos, err := msm.encodeLocalProtocols()
	if err != nil {
		return err
	}
	return delimWrite(w, protos)
}
func (msm *MultistreamMuxer) encodeLocalProtocols() ([]byte, error) {
	buf := new(bytes.Buffer)
	msm.handlerlock.RLock()
	for _, h := range msm.handlers {
		err := delimWrite(buf, []byte(h.AddName))
		if err != nil {
			msm.handlerlock.RUnlock()
			return nil, err
		}
	}
	msm.handlerlock.RUnlock()
	return buf.Bytes(), nil
}
func (msm *MultistreamMuxer) Handle(rwc io.ReadWriteCloser) error {
	p, h, err := msm.Negotiate(rwc)
	if err != nil {
		return err
	}
	return h(p, rwc)
}