github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/common/selector.go (about)

     1  package common
     2  
     3  import (
     4  	"errors"
     5  	"sort"
     6  
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  )
     9  
    10  var (
    11  	errDuplicateVersionSelector = errors.New("duplicate version ")
    12  	errRepeatRegisterSelector   = errors.New("repeat register selectors ")
    13  )
    14  
    15  var (
    16  	DefaultFactory = func(higherThan func(h int64) bool, version SelectVersion, internal interface{}) SelectorFactory {
    17  		return func() Selector {
    18  			return NewCommonHeightSelector(higherThan, version, internal)
    19  		}
    20  	}
    21  )
    22  
    23  // TODO,use genesis
    24  type Selector interface {
    25  	Version() SelectVersion
    26  	Select(ctx sdk.Context) (interface{}, bool)
    27  }
    28  
    29  type SelectVersion float64
    30  
    31  type SelectorFactory func() Selector
    32  
    33  type Selectors []Selector
    34  
    35  func (m Selectors) Len() int {
    36  	return len(m)
    37  }
    38  
    39  func (m Selectors) Less(i, j int) bool {
    40  	return m[i].Version() >= m[j].Version()
    41  }
    42  
    43  func (m Selectors) Swap(i, j int) {
    44  	m[i], m[j] = m[j], m[i]
    45  }
    46  
    47  // //////
    48  var (
    49  	_ Selector = (*CommonHeightSelector)(nil)
    50  )
    51  
    52  type CommonHeightSelector struct {
    53  	higherThan func(h int64) bool
    54  	version    SelectVersion
    55  	internal   interface{}
    56  }
    57  
    58  func NewCommonHeightSelector(higherThan func(h int64) bool, version SelectVersion, internal interface{}) *CommonHeightSelector {
    59  	return &CommonHeightSelector{higherThan: higherThan, version: version, internal: internal}
    60  }
    61  
    62  func (c *CommonHeightSelector) Version() SelectVersion {
    63  	return c.version
    64  }
    65  
    66  func (c *CommonHeightSelector) Select(ctx sdk.Context) (interface{}, bool) {
    67  	if c.higherThan(ctx.BlockHeight()) {
    68  		return c.internal, true
    69  	}
    70  	return nil, false
    71  }
    72  
    73  ///////
    74  
    75  type SelectorStrategy struct {
    76  	internal  interface{}
    77  	selectors Selectors
    78  	seal      bool
    79  }
    80  
    81  func (f *SelectorStrategy) RegisterSelectors(factories ...SelectorFactory) {
    82  	if f.Seald() {
    83  		panic(errDuplicateVersionSelector)
    84  	}
    85  	var selectors Selectors
    86  	set := make(map[SelectVersion]struct{})
    87  
    88  	for _, f := range factories {
    89  		sel := f()
    90  		selectors = append(selectors, sel)
    91  		v := sel.Version()
    92  		if _, contains := set[v]; contains {
    93  			panic(errDuplicateVersionSelector)
    94  		}
    95  		set[v] = struct{}{}
    96  	}
    97  	sort.Sort(selectors)
    98  
    99  	f.selectors = selectors
   100  }
   101  
   102  func NewSelectorStrategy(internal interface{}) *SelectorStrategy {
   103  	return &SelectorStrategy{internal: internal}
   104  }
   105  
   106  func (f *SelectorStrategy) Seald() bool {
   107  	return f.seal
   108  }
   109  func (f *SelectorStrategy) Seal() {
   110  	f.seal = true
   111  }
   112  
   113  func (f *SelectorStrategy) GetProxy(ctx sdk.Context) interface{} {
   114  	for _, s := range f.selectors {
   115  		m, ok := s.Select(ctx)
   116  		if ok {
   117  			return m
   118  		}
   119  	}
   120  	return f.internal
   121  }
   122  
   123  func (f *SelectorStrategy) GetInternal() interface{} {
   124  	return f.internal
   125  }