func (r *rsStream) Encode(data []io.Reader, parity []io.Writer) error {
	if len(data) != r.r.DataShards {
		return ErrTooFewShards
	}
	if len(parity) != r.r.ParityShards {
		return ErrTooFewShards
	}
	all := r.createSlice()
	defer r.blockPool.Put(all)
	in := all[:r.r.DataShards]
	out := all[r.r.DataShards:]
	read := 0
	for {
		err := r.readShards(in, data)
		switch err {
		case nil:
		case io.EOF:
			if read == 0 {
				return ErrShardNoData
			}
			return nil
		default:
			return err
		}
		out = trimShards(out, shardSize(in))
		read += shardSize(in)
		err = r.r.Encode(all)
		if err != nil {
			return err
		}
		err = r.writeShards(parity, out)
		if err != nil {
			return err
		}
	}
}
Encodes parity shards for a set of data shards.

Input is 'shards' containing readers for data shards followed by parity shards
io.Writer.

The number of shards must match the number given to NewStream().

Each reader must supply the same number of bytes.

The parity shards will be written to the writer.
The number of bytes written will match the input size.

If a data stream returns an error, a StreamReadError type error
will be returned. If a parity writer returns an error, a
StreamWriteError will be returned.
package reedsolomon
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"sync"
)
type StreamEncoder interface {
	Encode(data []io.Reader, parity []io.Writer) error
	Verify(shards []io.Reader) (bool, error)
	Reconstruct(valid []io.Reader, fill []io.Writer) error
	Split(data io.Reader, dst []io.Writer, size int64) (err error)
	Join(dst io.Writer, shards []io.Reader, outSize int64) error
}
type StreamReadError struct {
	Err    error  
	Stream int    
}
func (s StreamReadError) Error() string {
	return fmt.Sprintf("error reading stream %d: %s", s.Stream, s.Err)
}
func (s StreamReadError) String() string {
	return s.Error()
}
type StreamWriteError struct {
	Err    error  
	Stream int    
}
func (s StreamWriteError) Error() string {
	return fmt.Sprintf("error writing stream %d: %s", s.Stream, s.Err)
}
func (s StreamWriteError) String() string {
	return s.Error()
}
type rsStream struct {
	r *reedSolomon
	o options
	readShards func(dst [][]byte, in []io.Reader) error
	writeShards func(out []io.Writer, in [][]byte) error
	blockPool sync.Pool
}
func NewStream(dataShards, parityShards int, o ...Option) (StreamEncoder, error) {
	r := rsStream{o: defaultOptions}
	for _, opt := range o {
		opt(&r.o)
	}
	if r.o.streamBS == 0 && r.o.shardSize > 0 {
		r.o.streamBS = r.o.shardSize
	}
	if r.o.streamBS <= 0 {
		r.o.streamBS = 4 << 20
	}
	if r.o.shardSize == 0 && r.o.maxGoroutines == defaultOptions.maxGoroutines {
		o = append(o, WithAutoGoroutines(r.o.streamBS))
	}
	enc, err := New(dataShards, parityShards, o...)
	if err != nil {
		return nil, err
	}
	r.r = enc.(*reedSolomon)
	r.blockPool.New = func() interface{} {
		out := make([][]byte, dataShards+parityShards)
		for i := range out {
			out[i] = make([]byte, r.o.streamBS)
		}
		return out
	}
	r.readShards = readShards
	r.writeShards = writeShards
	if r.o.concReads {
		r.readShards = cReadShards
	}
	if r.o.concWrites {
		r.writeShards = cWriteShards
	}
	return &r, err
}
func NewStreamC(dataShards, parityShards int, conReads, conWrites bool, o ...Option) (StreamEncoder, error) {
	return NewStream(dataShards, parityShards, append(o, WithConcurrentStreamReads(conReads), WithConcurrentStreamWrites(conWrites))...)
}
func (r *rsStream) createSlice() [][]byte {
	out := r.blockPool.Get().([][]byte)
	for i := range out {
		out[i] = out[i][:r.o.streamBS]
	}
	return out
}