storj.io/uplink@v1.13.0/private/storage/streams/segmentupload/encode.go (about)

     1  // Copyright (C) 2023 Storj Labs, Inc.
     2  // See LICENSE for copying information.
     3  
     4  package segmentupload
     5  
     6  import (
     7  	"errors"
     8  	"io"
     9  
    10  	"github.com/zeebo/errs"
    11  
    12  	"storj.io/uplink/private/eestream"
    13  )
    14  
    15  // EncodedReader provides a redundant piece for given reader.
    16  type EncodedReader struct {
    17  	r         io.Reader
    18  	rs        eestream.RedundancyStrategy
    19  	num       int
    20  	stripeBuf []byte
    21  	shareBuf  []byte
    22  	available int
    23  	err       error
    24  }
    25  
    26  // NewEncodedReader provides a reader that returns a redundant piece for the
    27  // reader using the given redundancy strategy and piece number.
    28  func NewEncodedReader(r io.Reader, rs eestream.RedundancyStrategy, num int) *EncodedReader {
    29  	return &EncodedReader{
    30  		r:         r,
    31  		rs:        rs,
    32  		num:       num,
    33  		stripeBuf: make([]byte, rs.StripeSize()),
    34  		shareBuf:  make([]byte, rs.ErasureShareSize()),
    35  	}
    36  }
    37  
    38  // Read reads the redundant piece data.
    39  func (er *EncodedReader) Read(p []byte) (n int, err error) {
    40  	// No need to trace this function because it's very fast and called many times.
    41  	if er.err != nil {
    42  		return 0, er.err
    43  	}
    44  
    45  	for len(p) > 0 {
    46  		if er.available == 0 {
    47  			// take the next stripe from the segment buffer
    48  			_, err := io.ReadFull(er.r, er.stripeBuf)
    49  			if errors.Is(err, io.EOF) {
    50  				er.err = io.EOF
    51  				break
    52  			} else if err != nil {
    53  				er.err = errs.Wrap(err)
    54  				return 0, er.err
    55  			}
    56  
    57  			// encode the num-th erasure share
    58  			err = er.rs.EncodeSingle(er.stripeBuf, er.shareBuf, er.num)
    59  			if err != nil {
    60  				er.err = err
    61  				return 0, err
    62  			}
    63  
    64  			er.available = len(er.shareBuf)
    65  		}
    66  
    67  		off := len(er.shareBuf) - er.available
    68  		nc := copy(p, er.shareBuf[off:])
    69  		p = p[nc:]
    70  		er.available -= nc
    71  		n += nc
    72  	}
    73  
    74  	return n, er.err
    75  }