func (p *punctuatedReader) ReadUntilPunctuation(lim int) (res []byte, err error) {
	for {
		var n int
		n, err = p.Read(p.buf[:])
		if err == ErrPunctuated || err == nil {
			res = append(res, p.buf[0:n]...)
			if err == ErrPunctuated {
				err = nil
				return res, err
			}
			if len(res) >= lim {
				return nil, ErrOverflow
			}
		} else if err != nil {
			if err == io.EOF {
				err = io.ErrUnexpectedEOF
			}
			return nil, err
		} else if n == 0 {
			return nil, io.ErrUnexpectedEOF
		}
	}
}
ReadUntilPunctuation reads from the stream until it find a desired
punctuation byte. If it wasn't found before EOF, it will return io.ErrUnexpectedEOF.
If it wasn't found before lim bytes are consumed, then it will return ErrOverflow.
package saltpack
import (
	"bytes"
	"errors"
	"io"
)
type punctuatedReader struct {
	r              io.Reader
	punctuation    [1]byte
	nextSegment    []byte
	thisSegment    []byte
	errThisSegment error
	buf            [4096]byte
}
var ErrPunctuated = errors.New("found punctuation in stream")
var ErrOverflow = errors.New("buffer was overflowed before we found punctuation")
func (p *punctuatedReader) Read(out []byte) (n int, err error) {
	if len(p.thisSegment) > 0 {
		n = copy(out, p.thisSegment)
		p.thisSegment = p.thisSegment[n:]
		if len(p.thisSegment) == 0 {
			err = p.errThisSegment
			p.errThisSegment = nil
		}
		return n, err
	}
	var src []byte
	usedBuffer := false
	if len(p.nextSegment) > 0 {
		src = p.nextSegment
		usedBuffer = true
		p.nextSegment = nil
	} else {
		n, err = p.r.Read(out)
		if err != nil {
			return n, err
		}
		src = out[0:n]
	}
	foundPunc := false
	if i := bytes.Index(src, p.punctuation[:]); i >= 0 {
		p.nextSegment = src[(i + 1):]
		src = src[0:i]
		n = len(src)
		foundPunc = true
	}
	if usedBuffer {
		n = copy(out, src)
		p.thisSegment = src[n:]
	}
	if foundPunc {
		if len(p.thisSegment) > 0 {
			p.errThisSegment = ErrPunctuated
		} else {
			err = ErrPunctuated
		}
	}
	return n, err
}