github.com/Finschia/finschia-sdk@v0.48.1/x/capability/types/types.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	yaml "gopkg.in/yaml.v2"
     8  
     9  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    10  )
    11  
    12  // NewCapability returns a reference to a new Capability to be used as an
    13  // actual capability.
    14  func NewCapability(index uint64) *Capability {
    15  	return &Capability{Index: index}
    16  }
    17  
    18  // String returns the string representation of a Capability. The string contains
    19  // the Capability's memory reference as the string is to be used in a composite
    20  // key and to authenticate capabilities.
    21  func (ck *Capability) String() string {
    22  	return fmt.Sprintf("Capability{%p, %d}", ck, ck.Index)
    23  }
    24  
    25  func NewOwner(module, name string) Owner {
    26  	return Owner{Module: module, Name: name}
    27  }
    28  
    29  // Key returns a composite key for an Owner.
    30  func (o Owner) Key() string {
    31  	return fmt.Sprintf("%s/%s", o.Module, o.Name)
    32  }
    33  
    34  func (o Owner) String() string {
    35  	bz, _ := yaml.Marshal(o)
    36  	return string(bz)
    37  }
    38  
    39  func NewCapabilityOwners() *CapabilityOwners {
    40  	return &CapabilityOwners{Owners: make([]Owner, 0)}
    41  }
    42  
    43  // Set attempts to add a given owner to the CapabilityOwners. If the owner
    44  // already exists, an error will be returned. Set runs in O(log n) average time
    45  // and O(n) in the worst case.
    46  func (co *CapabilityOwners) Set(owner Owner) error {
    47  	i, ok := co.Get(owner)
    48  	if ok {
    49  		// owner already exists at co.Owners[i]
    50  		return sdkerrors.Wrapf(ErrOwnerClaimed, owner.String())
    51  	}
    52  
    53  	// owner does not exist in the set of owners, so we insert at position i
    54  	co.Owners = append(co.Owners, Owner{}) // expand by 1 in amortized O(1) / O(n) worst case
    55  	copy(co.Owners[i+1:], co.Owners[i:])
    56  	co.Owners[i] = owner
    57  
    58  	return nil
    59  }
    60  
    61  // Remove removes a provided owner from the CapabilityOwners if it exists. If the
    62  // owner does not exist, Remove is considered a no-op.
    63  func (co *CapabilityOwners) Remove(owner Owner) {
    64  	if len(co.Owners) == 0 {
    65  		return
    66  	}
    67  
    68  	i, ok := co.Get(owner)
    69  	if ok {
    70  		// owner exists at co.Owners[i]
    71  		co.Owners = append(co.Owners[:i], co.Owners[i+1:]...)
    72  	}
    73  }
    74  
    75  // Get returns (i, true) of the provided owner in the CapabilityOwners if the
    76  // owner exists, where i indicates the owner's index in the set. Otherwise
    77  // (i, false) where i indicates where in the set the owner should be added.
    78  func (co *CapabilityOwners) Get(owner Owner) (int, bool) {
    79  	// find smallest index s.t. co.Owners[i] >= owner in O(log n) time
    80  	i := sort.Search(len(co.Owners), func(i int) bool { return co.Owners[i].Key() >= owner.Key() })
    81  	if i < len(co.Owners) && co.Owners[i].Key() == owner.Key() {
    82  		// owner exists at co.Owners[i]
    83  		return i, true
    84  	}
    85  
    86  	return i, false
    87  }