github.com/mavryk-network/mvgo@v1.19.9/mavryk/set.go (about)

     1  // Copyright (c) 2020-2023 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package mavryk
     5  
     6  import (
     7  	"github.com/mavryk-network/mvgo/hash"
     8  )
     9  
    10  type AddressSet struct {
    11  	set  map[uint64]Address
    12  	coll []Address
    13  }
    14  
    15  func NewAddressSet(addrs ...Address) *AddressSet {
    16  	set := &AddressSet{
    17  		set: make(map[uint64]Address, len(addrs)),
    18  	}
    19  	for _, v := range addrs {
    20  		if !v.IsValid() {
    21  			continue
    22  		}
    23  		set.AddUnique(v)
    24  	}
    25  	return set
    26  }
    27  
    28  func BuildAddressSet(s ...string) (*AddressSet, error) {
    29  	set := NewAddressSet()
    30  	for _, v := range s {
    31  		addr, err := ParseAddress(v)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  		set.AddUnique(addr)
    36  	}
    37  	return set, nil
    38  }
    39  
    40  func MustBuildAddressSet(s ...string) *AddressSet {
    41  	set, err := BuildAddressSet(s...)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  	return set
    46  }
    47  
    48  func (s *AddressSet) AddUnique(addr Address) bool {
    49  	h := hash.Hash64(addr[:])
    50  	a, ok := s.set[h]
    51  	if ok {
    52  		if !a.Equal(addr) {
    53  			// hash collision
    54  			s.coll = append(s.coll, addr.Clone())
    55  			ok = false
    56  		}
    57  	} else {
    58  		s.set[h] = addr.Clone()
    59  	}
    60  	return !ok
    61  }
    62  
    63  func (s *AddressSet) Add(addr Address) {
    64  	s.AddUnique(addr)
    65  }
    66  
    67  func (s *AddressSet) Remove(addr Address) {
    68  	delete(s.set, hash.Hash64(addr[:]))
    69  	for i := range s.coll {
    70  		if !s.coll[i].Equal(addr) {
    71  			continue
    72  		}
    73  		s.coll = append(s.coll[:i], s.coll[i+1:]...)
    74  		return
    75  	}
    76  }
    77  
    78  func (s *AddressSet) Clear() {
    79  	for n := range s.set {
    80  		delete(s.set, n)
    81  	}
    82  	s.coll = s.coll[:0]
    83  }
    84  
    85  func (s *AddressSet) Contains(addr Address) bool {
    86  	if s == nil || len(s.set) == 0 {
    87  		return false
    88  	}
    89  	a, ok := s.set[hash.Hash64(addr[:])]
    90  	if !ok {
    91  		return false
    92  	}
    93  	if a.Equal(addr) {
    94  		return true
    95  	}
    96  	for _, v := range s.coll {
    97  		if v.Equal(addr) {
    98  			return true
    99  		}
   100  	}
   101  	return false
   102  }
   103  
   104  func (s *AddressSet) Merge(b *AddressSet) {
   105  	for bHash, bAddr := range b.set {
   106  		if aAddr, ok := s.set[bHash]; ok {
   107  			if !aAddr.Equal(bAddr) {
   108  				var found bool
   109  				for _, v := range s.coll {
   110  					if v.Equal(bAddr) {
   111  						found = true
   112  						break
   113  					}
   114  				}
   115  				if !found {
   116  					s.coll = append(s.coll, bAddr)
   117  				}
   118  			}
   119  		} else {
   120  			s.set[bHash] = bAddr.Clone()
   121  		}
   122  	}
   123  }
   124  
   125  func (s *AddressSet) Len() int {
   126  	return len(s.set) + len(s.coll)
   127  }
   128  
   129  func (s AddressSet) Map() map[uint64]Address {
   130  	return s.set
   131  }
   132  
   133  func (s AddressSet) HasCollisions() bool {
   134  	return len(s.coll) > 0
   135  }
   136  
   137  func (s AddressSet) Slice() []Address {
   138  	if len(s.set) == 0 {
   139  		return nil
   140  	}
   141  	a := make([]Address, 0, len(s.set))
   142  	for _, v := range s.Map() {
   143  		a = append(a, v)
   144  	}
   145  	a = append(a, s.coll...)
   146  	return a
   147  }
   148  
   149  func (s AddressSet) HasIntersect(t *AddressSet) bool {
   150  	for k, v := range s.set {
   151  		a, ok := t.set[k]
   152  		if !ok {
   153  			continue
   154  		}
   155  		if v.Equal(a) {
   156  			return true
   157  		}
   158  		for _, v := range t.coll {
   159  			if v.Equal(a) {
   160  				return true
   161  			}
   162  		}
   163  	}
   164  	for _, v := range s.coll {
   165  		if t.Contains(v) {
   166  			return true
   167  		}
   168  	}
   169  	return false
   170  }
   171  
   172  func (s AddressSet) Intersect(t *AddressSet) *AddressSet {
   173  	i := NewAddressSet()
   174  	for k, v := range s.set {
   175  		a, ok := t.set[k]
   176  		if !ok {
   177  			continue
   178  		}
   179  		if v.Equal(a) {
   180  			i.AddUnique(a)
   181  		} else {
   182  			for _, a := range t.coll {
   183  				if v.Equal(a) {
   184  					i.AddUnique(a)
   185  				}
   186  			}
   187  		}
   188  	}
   189  	for _, v := range s.coll {
   190  		if t.Contains(v) {
   191  			i.AddUnique(v)
   192  		}
   193  	}
   194  	return i
   195  }