func (ss *shareStack) peel(share []byte, delimited bool) (err error) {
	if delimited {
		var txLen uint64
		share, txLen, err = parseDelimiter(share)
		if err != nil {
			return err
		}
		if txLen == 0 {
			return nil
		}
		ss.txLen = txLen
	}
	safeLen := len(share) - binary.MaxVarintLen64
	if safeLen < 0 {
		safeLen = 0
	}
	if ss.txLen <= uint64(safeLen) {
		ss.txs = append(ss.txs, share[:ss.txLen])
		share = share[ss.txLen:]
		return ss.peel(share, true)
	}
	if len(ss.shares) > ss.cursor+1 {
		ss.cursor++
		share := append(share, ss.shares[ss.cursor][consts.NamespaceSize+consts.ShareReservedBytes:]...)
		return ss.peel(share, false)
	}
	if ss.txLen <= uint64(len(share)) {
		ss.txs = append(ss.txs, share[:ss.txLen])
		share = share[ss.txLen:]
		return ss.peel(share, true)
	}
	return errors.New("failure to parse block data: transaction length exceeded data length")
}
peel recursively parses each chunk of data (either a transaction,
intermediate state root, or evidence) and adds it to the underlying slice of data.
package types
import (
	"bytes"
	"encoding/binary"
	"errors"
	"github.com/celestiaorg/rsmt2d"
	"github.com/gogo/protobuf/proto"
	tmbytes "github.com/tendermint/tendermint/libs/bytes"
	"github.com/tendermint/tendermint/pkg/consts"
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
func DataFromSquare(eds *rsmt2d.ExtendedDataSquare) (Data, error) {
	originalWidth := eds.Width() / 2
	var (
		sortedTxShares  [][]byte
		sortedISRShares [][]byte
		sortedEvdShares [][]byte
		sortedMsgShares [][]byte
	)
	for x := uint(0); x < originalWidth; x++ {
		row := eds.Row(x)
		for _, share := range row[:originalWidth] {
			nid := share[:consts.NamespaceSize]
			switch {
			case bytes.Equal(consts.TxNamespaceID, nid):
				sortedTxShares = append(sortedTxShares, share)
			case bytes.Equal(consts.IntermediateStateRootsNamespaceID, nid):
				sortedISRShares = append(sortedISRShares, share)
			case bytes.Equal(consts.EvidenceNamespaceID, nid):
				sortedEvdShares = append(sortedEvdShares, share)
			case bytes.Equal(consts.TailPaddingNamespaceID, nid):
				continue
			case bytes.Compare(nid, consts.MaxReservedNamespace) < 1:
				continue
			default:
				sortedMsgShares = append(sortedMsgShares, share)
			}
		}
	}
	txs, err := parseTxs(sortedTxShares)
	if err != nil {
		return Data{}, err
	}
	isrs, err := parseISRs(sortedISRShares)
	if err != nil {
		return Data{}, err
	}
	evd, err := parseEvd(sortedEvdShares)
	if err != nil {
		return Data{}, err
	}
	msgs, err := parseMsgs(sortedMsgShares)
	if err != nil {
		return Data{}, err
	}
	return Data{
		Txs:                    txs,
		IntermediateStateRoots: isrs,
		Evidence:               evd,
		Messages:               msgs,
	}, nil
}
func parseTxs(shares [][]byte) (Txs, error) {
	rawTxs, err := processContiguousShares(shares)
	if err != nil {
		return nil, err
	}
	txs := make(Txs, len(rawTxs))
	for i := 0; i < len(txs); i++ {
		txs[i] = Tx(rawTxs[i])
	}
	return txs, nil
}
func parseISRs(shares [][]byte) (IntermediateStateRoots, error) {
	rawISRs, err := processContiguousShares(shares)
	if err != nil {
		return IntermediateStateRoots{}, err
	}
	ISRs := make([]tmbytes.HexBytes, len(rawISRs))
	for i := 0; i < len(ISRs); i++ {
		ISRs[i] = rawISRs[i]
	}
	return IntermediateStateRoots{RawRootsList: ISRs}, nil
}
func parseEvd(shares [][]byte) (EvidenceData, error) {
	rawEvd, err := processContiguousShares(shares)
	if err != nil {
		return EvidenceData{}, err
	}
	evdList := make(EvidenceList, len(rawEvd))
	for i := 0; i < len(rawEvd); i++ {
		var protoEvd tmproto.Evidence
		err := proto.Unmarshal(rawEvd[i], &protoEvd)
		if err != nil {
			return EvidenceData{}, err
		}
		evd, err := EvidenceFromProto(&protoEvd)
		if err != nil {
			return EvidenceData{}, err
		}
		evdList[i] = evd
	}
	return EvidenceData{Evidence: evdList}, nil
}
func parseMsgs(shares [][]byte) (Messages, error) {
	msgList, err := parseMsgShares(shares)
	if err != nil {
		return Messages{}, err
	}
	return Messages{
		MessagesList: msgList,
	}, nil
}
func processContiguousShares(shares [][]byte) (txs [][]byte, err error) {
	if len(shares) == 0 {
		return nil, nil
	}
	ss := newShareStack(shares)
	return ss.resolve()
}
type shareStack struct {
	shares [][]byte
	txLen  uint64
	txs    [][]byte
	cursor int
}
func newShareStack(shares [][]byte) *shareStack {
	return &shareStack{shares: shares}
}
func (ss *shareStack) resolve() ([][]byte, error) {
	if len(ss.shares) == 0 {
		return nil, nil
	}
	err := ss.peel(ss.shares[0][consts.NamespaceSize+consts.ShareReservedBytes:], true)
	return ss.txs, err
}