You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: encoder.go
    path of file: ./repos/go-git/plumbing/format/commitgraph/v2
    
    the code of the file until where you have to start completion: package v2

import (
	"crypto"
	"io"
	"math"

	"github.com/go-git/go-git/v5/plumbing"
	"github.com/go-git/go-git/v5/plumbing/hash"
	"github.com/go-git/go-git/v5/utils/binary"
)

// Encoder writes MemoryIndex structs to an output stream.
type Encoder struct {
	io.Writer
	hash hash.Hash
}

// NewEncoder returns a new stream encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
	h := hash.New(hash.CryptoType)
	mw := io.MultiWriter(w, h)
	return &Encoder{mw, h}
}

// Encode writes an index into the commit-graph file
func (e *Encoder) Encode(idx Index) error {
	// Get all the hashes in the input index
	hashes := idx.Hashes()

	// Sort the inout and prepare helper structures we'll need for encoding
	hashToIndex, fanout, extraEdgesCou
    
func (e *Encoder) encodeCommitData(hashes []plumbing.Hash, hashToIndex map[plumbing.Hash]uint32, idx Index) (extraEdges []uint32, generationV2Data []uint64, err error) {
	if idx.HasGenerationV2() {
		generationV2Data = make([]uint64, 0, len(hashes))
	}
	for _, hash := range hashes {
		origIndex, _ := idx.GetIndexByHash(hash)
		commitData, _ := idx.GetCommitDataByIndex(origIndex)
		if _, err = e.Write(commitData.TreeHash[:]); err != nil {
			return
		}

		var parent1, parent2 uint32
		if len(commitData.ParentHashes) == 0 {
			parent1 = parentNone
			parent2 = parentNone
		} else if len(commitData.ParentHashes) == 1 {
			parent1 = hashToIndex[commitData.ParentHashes[0]]
			parent2 = parentNone
		} else if len(commitData.ParentHashes) == 2 {
			parent1 = hashToIndex[commitData.ParentHashes[0]]
			parent2 = hashToIndex[commitData.ParentHashes[1]]
		} else if len(commitData.ParentHashes) > 2 {
			parent1 = hashToIndex[commitData.ParentHashes[0]]
			parent2 = uint32(len(extraEdges)) | parentOctopusUsed
			for _, parentHash := range commitData.ParentHashes[1:] {
				extraEdges = append(extraEdges, hashToIndex[parentHash])
			}
			extraEdges[len(extraEdges)-1] |= parentLast
		}

		if err = binary.WriteUint32(e, parent1); err == nil {
			err = binary.WriteUint32(e, parent2)
		}
		if err != nil {
			return
		}

		unixTime := uint64(commitData.When.Unix())
		unixTime |= uint64(commitData.Generation) << 34
		if err = binary.WriteUint64(e, unixTime); err != nil {
			return
		}
		if generationV2Data != nil {
			generationV2Data = append(generationV2Data, commitData.GenerationV2Data())
		}
	}
	return
}