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: msg_dropindexes.go
    path of file: ./repos/FerretDB/internal/handler
    
    the code of the file until where you have to start completion: // Copyright 2021 FerretDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package handler

import (
	"context"
	"errors"
	"fmt"

	"github.com/FerretDB/FerretDB/internal/backends"
	"github.com/FerretDB/FerretDB/internal/handler/common"
	"github.com/FerretDB/FerretDB/internal/handler/handlererrors"
	"github.com/FerretDB/FerretDB/internal/handler/handlerparams"
	"github.com/FerretDB/FerretDB/internal/types"
	"github.com/FerretDB/FerretDB/internal/util/iterator"
	"github.com/FerretDB/FerretDB/internal/util/lazyerrors"
	"github.com/FerretDB/FerretDB/internal/util/must"
	"github.com/FerretDB/FerretDB/internal/wire"
)

// MsgDropIndexes implements `dropIndexes` command.
func (h *Handler) MsgDropIndexes(ctx context.Context, msg *wire.OpMsg) (*wire.OpMsg, error) {
	document, err := msg.Document()
	if err != nil {
		return nil, lazyerrors.Error(err)
	}

	command := document.Command()

	dbName, err := common.GetRequiredParam[string](document, "$db")
	if err != nil {
		return nil, err
	}

	collection, err :=
    
func processDropIndexOptions(command, ns string, v any, existing []backends.IndexInfo) ([]string, bool, error) { //nolint:lll // for readability
	switch v := v.(type) {
	case *types.Document:
		// Index specification (key) is provided to drop a specific index.
		var spec []backends.IndexKeyPair

		spec, err := processIndexKey(command, v)
		if err != nil {
			return nil, false, lazyerrors.Error(err)
		}

		if len(spec) == 1 && spec[0].Field == "_id" && !spec[0].Descending {
			return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
				handlererrors.ErrInvalidOptions, "cannot drop _id index", command,
			)
		}

		if len(existing) == 0 {
			return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
				handlererrors.ErrNamespaceNotFound, fmt.Sprintf("ns not found %s", ns), command,
			)
		}

		for _, index := range existing {
			matches := true

			for i, key := range index.Key {
				if key.Field != spec[i].Field || key.Descending != spec[i].Descending {
					matches = false
					break
				}
			}

			if matches {
				return []string{index.Name}, false, nil
			}
		}

		msg := fmt.Sprintf("can't find index with key: { %v }", formatIndexKey(spec))

		return nil, false, handlererrors.NewCommandErrorMsgWithArgument(handlererrors.ErrIndexNotFound, msg, command)

	case *types.Array:
		// List of index names is provided to drop multiple indexes.
		iter := v.Iterator()

		defer iter.Close() // it's safe to defer here as the iterators reads everything

		toDrop := make([]string, 0, v.Len())

		for {
			var val any

			_, val, err := iter.Next()
			if err != nil {
				if errors.Is(err, iterator.ErrIteratorDone) {
					return toDrop, false, nil
				}

				return nil, false, lazyerrors.Error(err)
			}

			index, ok := val.(string)
			if !ok {
				return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
					handlererrors.ErrTypeMismatch,
					fmt.Sprintf(
						"BSON field 'dropIndexes.index' is the wrong type '%s', expected types '[string, object]'",
						handlerparams.AliasFromType(v),
					),
					command,
				)
			}

			if len(existing) == 0 {
				return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
					handlererrors.ErrNamespaceNotFound, fmt.Sprintf("ns not found %s", ns), command,
				)
			}

			if index == backends.DefaultIndexName {
				return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
					handlererrors.ErrInvalidOptions, "cannot drop _id index", command,
				)
			}

			var found bool

			for _, existingIndex := range existing {
				if index == existingIndex.Name {
					toDrop = append(toDrop, index)
					found = true

					break
				}
			}

			if !found {
				return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
					handlererrors.ErrIndexNotFound,
					fmt.Sprintf("index not found with name [%s]", index),
					command,
				)
			}
		}

	case string:
		if v == "*" {
			toDrop := make([]string, 0, len(existing))

			// Drop all indexes except the _id index.
			for _, index := range existing {
				if index.Name == backends.DefaultIndexName {
					continue
				}

				toDrop = append(toDrop, index.Name)
			}

			return toDrop, true, nil
		}

		if len(existing) == 0 {
			return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
				handlererrors.ErrNamespaceNotFound, fmt.Sprintf("ns not found %s", ns), command,
			)
		}

		if v == backends.DefaultIndexName {
			return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
				handlererrors.ErrInvalidOptions, "cannot drop _id index", command,
			)
		}

		for _, existingIndex := range existing {
			if v == existingIndex.Name {
				return []string{v}, false, nil
			}
		}

		return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
			handlererrors.ErrIndexNotFound,
			fmt.Sprintf("index not found with name [%s]", v),
			command,
		)
	}

	return nil, false, handlererrors.NewCommandErrorMsgWithArgument(
		handlererrors.ErrTypeMismatch,
		fmt.Sprintf(
			"BSON field 'dropIndexes.index' is the wrong type '%s', expected types '[string, object]'",
			handlerparams.AliasFromType(v),
		),
		command,
	)
}