github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/keyset/keyset.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package keyset
     7  
     8  import "github.com/insolar/vanilla/longbits"
     9  
    10  type Key = longbits.ByteString
    11  
    12  // A basic set of keys, that can be wrapped by an extra keyset logic.
    13  type KeyList interface {
    14  	// returns true when the given key is within the set
    15  	Contains(Key) bool
    16  	// lists keys
    17  	EnumKeys(func(k Key) bool) bool
    18  	// number of unique keys
    19  	Count() int
    20  }
    21  
    22  // An advanced set of keys, that also represent an open set (tracks exclusions, not inclusions)
    23  //
    24  // NB! An immutable inclusive/closed set MUST be able to cast to KeyList & InclusiveKeySet.
    25  // An open or a mutable KeySet MUST NOT be able to cast to KeyList & InclusiveKeySet.
    26  // This behavior is supported by this package.
    27  //
    28  type KeySet interface {
    29  	// returns true when this set is empty
    30  	IsNothing() bool
    31  	// returns true when this set matches everything
    32  	IsEverything() bool
    33  	// returns true when the set is open / unbound and only Contains exclusions
    34  	IsOpenSet() bool
    35  	// returns true when the given key is within the set
    36  	Contains(Key) bool
    37  	// returns true when any key of the given set is within this set
    38  	ContainsAny(KeySet) bool
    39  
    40  	// returns true when this set Contains all keys from the given one
    41  	SupersetOf(KeySet) bool
    42  	// returns true when all keys of this set are contained in the given one
    43  	SubsetOf(KeySet) bool
    44  	// returns true when both sets have same set of keys
    45  	Equal(KeySet) bool
    46  	// a faster equivalent of Equal(ks.Inverse())
    47  	EqualInverse(KeySet) bool
    48  
    49  	// returns a set that has all keys but this set
    50  	Inverse() KeySet
    51  	// returns a set of keys present in at least one sets
    52  	Union(KeySet) KeySet
    53  	// returns a set of keys present in both sets
    54  	Intersect(KeySet) KeySet
    55  	// returns a set of keys present in this set and not present in the given set
    56  	Subtract(KeySet) KeySet
    57  
    58  	// WARNING! Do not use
    59  	// lists keys (when IsOpenSet() == true, as then it lists _excluded_ keys)
    60  	EnumRawKeys(func(k Key, exclusive bool) bool) bool
    61  	// WARNING! Do not use. This must NOT be treated as a size of a set.
    62  	// number of keys (when IsOpenSet() == true, as then it gives a number of _excluded_ keys)
    63  	RawKeyCount() int
    64  }
    65  
    66  type InclusiveKeySet interface {
    67  	KeySet
    68  	// lists keys
    69  	EnumKeys(func(k Key) bool) bool
    70  	// number of unique keys
    71  	Count() int
    72  }
    73  
    74  func New(keys []Key) KeySet {
    75  	n := len(keys)
    76  	switch n {
    77  	case 0:
    78  		return Nothing()
    79  	case 1:
    80  		return SoloKeySet(keys[0])
    81  	}
    82  
    83  	ks := make(basicKeySet, n)
    84  	for _, k := range keys {
    85  		ks.add(k)
    86  	}
    87  	return inclusiveKeySet{ks}
    88  }
    89  
    90  func Wrap(keys KeyList) KeySet {
    91  	if keys == nil {
    92  		panic("illegal state")
    93  	}
    94  	return inclusiveKeySet{listSet{keys}}
    95  }
    96  
    97  func CopyList(keys KeyList) KeySet {
    98  	n := keys.Count()
    99  	if n == 0 {
   100  		return Nothing()
   101  	}
   102  	return inclusiveKeySet{listSet{keys}.copy(0)}
   103  }
   104  
   105  func CopySet(keys KeySet) KeySet {
   106  	if iks, ok := keys.(internalKeySet); ok {
   107  		return newKeySet(keys.IsOpenSet(), iks.copy(0))
   108  	}
   109  
   110  	switch n := keys.RawKeyCount(); {
   111  	case n > 0:
   112  		ks := make(basicKeySet, n)
   113  		keys.EnumRawKeys(func(k Key, _ bool) bool {
   114  			ks.add(k)
   115  			return false
   116  		})
   117  		return newKeySet(keys.IsOpenSet(), ks)
   118  	case n != 0:
   119  		panic("illegal state")
   120  	case keys.IsOpenSet():
   121  		return Everything()
   122  	default:
   123  		return Nothing()
   124  	}
   125  }
   126  
   127  func newKeySet(exclusive bool, ks internalKeySet) KeySet {
   128  	switch {
   129  	case ks == nil:
   130  		panic("illegal value")
   131  	case exclusive:
   132  		return exclusiveKeySet{ks}
   133  	default:
   134  		return inclusiveKeySet{ks}
   135  	}
   136  }