github.com/NebulousLabs/Sia@v1.3.7/modules/renter/erasure.go (about) 1 package renter 2 3 import ( 4 "fmt" 5 "io" 6 7 "github.com/klauspost/reedsolomon" 8 9 "github.com/NebulousLabs/Sia/modules" 10 ) 11 12 // rsCode is a Reed-Solomon encoder/decoder. It implements the 13 // modules.ErasureCoder interface. 14 type rsCode struct { 15 enc reedsolomon.Encoder 16 17 numPieces int 18 dataPieces int 19 } 20 21 // NumPieces returns the number of pieces returned by Encode. 22 func (rs *rsCode) NumPieces() int { return rs.numPieces } 23 24 // MinPieces return the minimum number of pieces that must be present to 25 // recover the original data. 26 func (rs *rsCode) MinPieces() int { return rs.dataPieces } 27 28 // Encode splits data into equal-length pieces, some containing the original 29 // data and some containing parity data. 30 func (rs *rsCode) Encode(data []byte) ([][]byte, error) { 31 pieces, err := rs.enc.Split(data) 32 if err != nil { 33 return nil, err 34 } 35 // err should not be possible if Encode is called on the result of Split, 36 // but no harm in checking anyway. 37 err = rs.enc.Encode(pieces) 38 if err != nil { 39 return nil, err 40 } 41 return pieces, nil 42 } 43 44 // EncodeShards creates the parity shards for an already sharded input. 45 func (rs *rsCode) EncodeShards(pieces [][]byte) ([][]byte, error) { 46 // Check that the caller provided the minimum amount of pieces. 47 if len(pieces) != rs.MinPieces() { 48 return nil, fmt.Errorf("invalid number of pieces given %v %v", len(pieces), rs.MinPieces()) 49 } 50 // Add the parity shards to pieces. 51 for len(pieces) < rs.NumPieces() { 52 pieces = append(pieces, make([]byte, pieceSize)) 53 } 54 err := rs.enc.Encode(pieces) 55 if err != nil { 56 return nil, err 57 } 58 return pieces, nil 59 } 60 61 // Recover recovers the original data from pieces and writes it to w. 62 // pieces should be identical to the slice returned by Encode (length and 63 // order must be preserved), but with missing elements set to nil. 64 func (rs *rsCode) Recover(pieces [][]byte, n uint64, w io.Writer) error { 65 err := rs.enc.ReconstructData(pieces) 66 if err != nil { 67 return err 68 } 69 return rs.enc.Join(w, pieces, int(n)) 70 } 71 72 // NewRSCode creates a new Reed-Solomon encoder/decoder using the supplied 73 // parameters. 74 func NewRSCode(nData, nParity int) (modules.ErasureCoder, error) { 75 enc, err := reedsolomon.New(nData, nParity) 76 if err != nil { 77 return nil, err 78 } 79 return &rsCode{ 80 enc: enc, 81 numPieces: nData + nParity, 82 dataPieces: nData, 83 }, nil 84 }