@@ -2,6 +2,7 @@ package ec
22
33import (
44 "fmt"
5+ "iter"
56 "slices"
67 "strconv"
78
@@ -40,10 +41,9 @@ func Encode(rule Rule, data []byte) ([][]byte, error) {
4041 return make ([][]byte , rule .DataPartNum + rule .ParityPartNum ), nil
4142 }
4243
43- // TODO: Explore reedsolomon.Option for performance improvement. https://github.com/nspcc-dev/neofs-node/issues/3501
44- enc , err := reedsolomon .New (int (rule .DataPartNum ), int (rule .ParityPartNum ))
45- if err != nil { // should never happen with correct rule
46- return nil , fmt .Errorf ("init Reed-Solomon encoder: %w" , err )
44+ enc , err := newCoderForRule (rule )
45+ if err != nil {
46+ return nil , err
4747 }
4848
4949 parts , err := enc .Split (data )
@@ -61,26 +61,44 @@ func Encode(rule Rule, data []byte) ([][]byte, error) {
6161// Decode decodes source data of known len from EC parts obtained by applying
6262// specified rule.
6363func Decode (rule Rule , dataLen uint64 , parts [][]byte ) ([]byte , error ) {
64- // TODO: Explore reedsolomon.Option for performance improvement. https://github.com/nspcc-dev/neofs-node/issues/3501
65- dec , err := reedsolomon .New (int (rule .DataPartNum ), int (rule .ParityPartNum ))
66- if err != nil { // should never happen with correct rule
67- return nil , fmt .Errorf ("init Reed-Solomon decoder: %w" , err )
64+ if err := decodeIndex (rule , parts , func (yield func (int ) bool ) {
65+ for i := range int (rule .DataPartNum ) {
66+ if ! yield (i ) {
67+ return
68+ }
69+ }
70+ }); err != nil {
71+ return nil , err
6872 }
6973
70- required := make ([]bool , rule .DataPartNum + rule .ParityPartNum )
71- for i := range rule .DataPartNum {
72- required [i ] = true
74+ if got := islices .TwoDimSliceElementCount (parts [:rule .DataPartNum ]); uint64 (got ) < dataLen {
75+ return nil , fmt .Errorf ("sum len of received data parts is less than full len: %d < %d" , got , dataLen )
76+ }
77+
78+ return ConcatDataParts (rule , dataLen , parts ), nil
79+ }
80+
81+ // DecodeIndexes decodes specified EC parts obtained by applying specified rule.
82+ func DecodeIndexes (rule Rule , parts [][]byte , idxs []int ) error {
83+ return decodeIndex (rule , parts , slices .Values (idxs ))
84+ }
85+
86+ func decodeIndex (rule Rule , parts [][]byte , idxs iter.Seq [int ]) error {
87+ rs , err := newCoderForRule (rule )
88+ if err != nil {
89+ return err
7390 }
7491
75- if err := dec .ReconstructSome (parts , required ); err != nil {
76- return nil , fmt .Errorf ("restore Reed-Solomon: %w" , err )
92+ required := make ([]bool , rule .DataPartNum + rule .ParityPartNum )
93+ for idx := range idxs {
94+ required [idx ] = true
7795 }
7896
79- if got := islices . TwoDimSliceElementCount (parts [: rule . DataPartNum ] ); uint64 ( got ) < dataLen {
80- return nil , fmt .Errorf ("sum len of received data parts is less than full len : %d < %d " , got , dataLen )
97+ if err := rs . ReconstructSome (parts , required ); err != nil {
98+ return fmt .Errorf ("restore Reed-Solomon : %w " , err )
8199 }
82100
83- return ConcatDataParts ( rule , dataLen , parts ), nil
101+ return nil
84102}
85103
86104// ConcatDataParts returns a new slice of dataLen bytes originating given EC
@@ -91,3 +109,13 @@ func ConcatDataParts(rule Rule, dataLen uint64, parts [][]byte) []byte {
91109 // TODO: last part may be shorter, do not overallocate buffer.
92110 return slices .Concat (parts [:rule .DataPartNum ]... )[:dataLen ]
93111}
112+
113+ func newCoderForRule (rule Rule ) (reedsolomon.Encoder , error ) {
114+ // TODO: Explore reedsolomon.Option for performance improvement. https://github.com/nspcc-dev/neofs-node/issues/3501
115+ enc , err := reedsolomon .New (int (rule .DataPartNum ), int (rule .ParityPartNum ))
116+ if err != nil { // should never happen with correct rule
117+ return nil , fmt .Errorf ("init Reed-Solomon decoder: %w" , err )
118+ }
119+
120+ return enc , nil
121+ }
0 commit comments