func (a *Applier) ApplyFile(dst io.Writer, f *File) error {
	if a.applyType != applyInitial {
		return applyError(errApplyInProgress)
	}
	defer func() { a.applyType = applyFile }()
	if f.IsBinary && len(f.TextFragments) > 0 {
		return applyError(errors.New("binary file contains text fragments"))
	}
	if !f.IsBinary && f.BinaryFragment != nil {
		return applyError(errors.New("text file contains binary fragment"))
	}
	switch {
	case f.BinaryFragment != nil:
		return a.ApplyBinaryFragment(dst, f.BinaryFragment)
	case len(f.TextFragments) > 0:
		frags := make([]*TextFragment, len(f.TextFragments))
		copy(frags, f.TextFragments)
		sort.Slice(frags, func(i, j int) bool {
			return frags[i].OldPosition < frags[j].OldPosition
		})
		for i, frag := range frags {
			if err := a.ApplyTextFragment(dst, frag); err != nil {
				return applyError(err, fragNum(i))
			}
		}
	}
	return applyError(a.Flush(dst))
}
ApplyFile applies the changes in all of the fragments of f and writes the
result to dst.
package gitdiff
import (
	"errors"
	"fmt"
	"io"
	"sort"
)
type Conflict struct {
	msg string
}
func (c *Conflict) Error() string {
	return "conflict: " + c.msg
}
func (c *Conflict) Is(other error) bool {
	if other, ok := other.(*Conflict); ok {
		return other.msg == "" || other.msg == c.msg
	}
	return false
}
type ApplyError struct {
	Line int64
	Fragment int
	FragmentLine int
	err error
}
func (e *ApplyError) Unwrap() error {
	return e.err
}
func (e *ApplyError) Error() string {
	return fmt.Sprintf("%v", e.err)
}
type lineNum int
type fragNum int
type fragLineNum int
func applyError(err error, args ...interface{}) error {
	if err == nil {
		return nil
	}
	e, ok := err.(*ApplyError)
	if !ok {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		e = &ApplyError{err: err}
	}
	for _, arg := range args {
		switch v := arg.(type) {
		case lineNum:
			e.Line = int64(v) + 1
		case fragNum:
			e.Fragment = int(v) + 1
		case fragLineNum:
			e.FragmentLine = int(v) + 1
		}
	}
	return e
}
var (
	errApplyInProgress = errors.New("gitdiff: incompatible apply in progress")
)
const (
	applyInitial = iota
	applyText
	applyBinary
	applyFile
)
func Apply(dst io.Writer, src io.ReaderAt, f *File) error {
	return NewApplier(src).ApplyFile(dst, f)
}
type Applier struct {
	src       io.ReaderAt
	lineSrc   LineReaderAt
	nextLine  int64
	applyType int
}
func NewApplier(src io.ReaderAt) *Applier {
	a := new(Applier)
	a.Reset(src)
	return a
}
func (a *Applier) Reset(src io.ReaderAt) {
	if src != nil {
		a.src = src
		if lineSrc, ok := src.(LineReaderAt); ok {
			a.lineSrc = lineSrc
		} else {
			a.lineSrc = &lineReaderAt{r: src}
		}
	}
	a.nextLine = 0
	a.applyType = applyInitial
}