// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package index import ( "github.com/hashicorp/consul/proto-public/pbresource" iradix "github.com/hashicorp/go-immutable-radix/v2" ) type Index struct { name string required bool indexer MultiIndexer } func New(name string, i Indexer, opts ...IndexOption) *Index { if name == "" { panic("all indexers must have a non-empty name") } if i == nil { panic("no indexer was supplied when creating a new cache Index") } var multiIndexer MultiIndexer switch v := i.(type) { case SingleIndexer: multiIndexer = singleIndexWrapper{indexer: v} case MultiIndexer: multiIndexer = v default: panic("The Indexer must also implement one of the SingleIndexer or MultiIndexer interfaces") } idx := &Index{ name: name, indexer: multiIndexer, } for _, opt := range opts { opt(idx) } return idx } func (i *Index) Name() string { return i.name } // IndexedData combines the Index with an radix tree for index and resource storage. func (i *Index) IndexedData() *IndexedData { return &IndexedData{ Index: i, tree: iradix.New[[]*pbresource.Resource](), } } // IndexedData is a wrapper around an Index and an radix tree for index and resource storage. type IndexedData struct { *Index tree *iradix.Tree[[]*pbresource.Resource] } func (i *IndexedData) Txn() Txn { return &txn{ inner: i.tree.Txn(), index: i, dirty: false, } } func (i *Index) fromArgs(args ...any) ([]byte, error) { return i.indexer.FromArgs(args...) } func (i *Index) fromResource(r *pbresource.Resource) (bool, [][]byte, error) { return i.indexer.FromResource(r) } type singleIndexWrapper struct { indexer SingleIndexer } func (s singleIndexWrapper) FromArgs(args ...any) ([]byte, error) { return s.indexer.FromArgs(args...) } func (s singleIndexWrapper) FromResource(r *pbresource.Resource) (bool, [][]byte, error) { indexed, val, err := s.indexer.FromResource(r) if err != nil || !indexed { return false, nil, err } return true, [][]byte{val}, nil }