func matchAfterPrefix(buf, prefix []byte, readErr error) int {
	if len(buf) == len(prefix) {
		if readErr != nil {
			return +1
		}
		return 0
	}
	c := buf[len(prefix)]
	if c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '-' {
		return +1
	}
	return -1
}
matchAfterPrefix checks whether buf should be considered to match the boundary.
The prefix is "--boundary" or "\r\n--boundary" or "\n--boundary",
and the caller has verified already that bytes.HasPrefix(buf, prefix) is true.

matchAfterPrefix returns +1 if the buffer does match the boundary,
meaning the prefix is followed by a dash, space, tab, cr, nl, or end of input.
It returns -1 if the buffer definitely does NOT match the boundary,
meaning the prefix is followed by some other character.
For example, "--foobar" does not match "--foo".
It returns 0 more input needs to be read to make the decision,
meaning that len(buf) == len(prefix) and readErr == nil.
package textproto
import (
	"bufio"
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
)
var emptyParams = make(map[string]string)
const peekBufferSize = 4096
type Part struct {
	Header Header
	mr *MultipartReader
	r io.Reader
	n       int    
	total   int64  
	err     error  
	readErr error  
}
func NewMultipartReader(r io.Reader, boundary string) *MultipartReader {
	b := []byte("\r\n--" + boundary + "--")
	return &MultipartReader{
		bufReader:        bufio.NewReaderSize(&stickyErrorReader{r: r}, peekBufferSize),
		nl:               b[:2],
		nlDashBoundary:   b[:len(b)-2],
		dashBoundaryDash: b[2:],
		dashBoundary:     b[2 : len(b)-2],
	}
}
type stickyErrorReader struct {
	r   io.Reader
	err error
}
func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
	if r.err != nil {
		return 0, r.err
	}
	n, r.err = r.r.Read(p)
	return n, r.err
}
func newPart(mr *MultipartReader) (*Part, error) {
	bp := &Part{mr: mr}
	if err := bp.populateHeaders(); err != nil {
		return nil, err
	}
	bp.r = partReader{bp}
	return bp, nil
}
func (bp *Part) populateHeaders() error {
	header, err := ReadHeader(bp.mr.bufReader)
	if err == nil {
		bp.Header = header
	}
	return err
}
func (p *Part) Read(d []byte) (n int, err error) {
	return p.r.Read(d)
}
type partReader struct {
	p *Part
}
func (pr partReader) Read(d []byte) (int, error) {
	p := pr.p
	br := p.mr.bufReader
	for p.n == 0 && p.err == nil {
		peek, _ := br.Peek(br.Buffered())
		p.n, p.err = scanUntilBoundary(peek, p.mr.dashBoundary, p.mr.nlDashBoundary, p.total, p.readErr)
		if p.n == 0 && p.err == nil {
			_, p.readErr = br.Peek(len(peek) + 1)
			if p.readErr == io.EOF {
				p.readErr = io.ErrUnexpectedEOF
			}
		}
	}
	if p.n == 0 {
		return 0, p.err
	}
	n := len(d)
	if n > p.n {
		n = p.n
	}
	n, _ = br.Read(d[:n])
	p.total += int64(n)
	p.n -= n
	if p.n == 0 {
		return n, p.err
	}
	return n, nil
}
func scanUntilBoundary(buf, dashBoundary, nlDashBoundary []byte, total int64, readErr error) (int, error) {
	if total == 0 {
		if bytes.HasPrefix(buf, dashBoundary) {
			switch matchAfterPrefix(buf, dashBoundary, readErr) {
			case -1:
				return len(dashBoundary), nil
			case 0:
				return 0, nil
			case +1:
				return 0, io.EOF
			}
		}
		if bytes.HasPrefix(dashBoundary, buf) {
			return 0, readErr
		}
	}
	if i := bytes.Index(buf, nlDashBoundary); i >= 0 {
		switch matchAfterPrefix(buf[i:], nlDashBoundary, readErr) {
		case -1:
			return i + len(nlDashBoundary), nil
		case 0:
			return i, nil
		case +1:
			return i, io.EOF
		}
	}
	if bytes.HasPrefix(nlDashBoundary, buf) {
		return 0, readErr
	}
	i := bytes.LastIndexByte(buf, nlDashBoundary[0])
	if i >= 0 && bytes.HasPrefix(nlDashBoundary, buf[i:]) {
		return i, nil
	}
	return len(buf), readErr
}