ruleset.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package firewall
  2. import (
  3. "iter"
  4. "math/bits"
  5. )
  6. // ruleSet is a set of rule ids, stored as a bitset. s[i] holds ids i*8 through i*8+7, one per bit.
  7. // Bytes rather than words keep a set to the size the rule count needs, which matters when there is a set for
  8. // every port number.
  9. type ruleSet []uint8
  10. // ruleSetLen returns the length of a ruleSet that can hold ids below n.
  11. func ruleSetLen(n int) int {
  12. return (n + 7) / 8
  13. }
  14. // newRuleSet returns an empty set that can hold ids below idLimit.
  15. func newRuleSet(idLimit int) ruleSet {
  16. return make(ruleSet, ruleSetLen(idLimit))
  17. }
  18. // add puts id in s.
  19. func (s ruleSet) add(id int) {
  20. s[id/8] |= 1 << (id % 8)
  21. }
  22. // ruleSets holds several ruleSet objects of the same length in a single allocation.
  23. type ruleSets struct {
  24. // setLen is the number of bytes needed to represent one set
  25. setLen int
  26. // bits holds the sets in order. Set i starts at i*setLen.
  27. bits []uint8
  28. }
  29. // newRuleSets returns n empty sets, each of which can hold ids below idLimit.
  30. func newRuleSets(n, idLimit int) ruleSets {
  31. setLen := ruleSetLen(idLimit)
  32. return ruleSets{setLen: setLen, bits: make([]uint8, n*setLen)}
  33. }
  34. // at returns set i.
  35. func (s ruleSets) at(i int) ruleSet {
  36. return s.bits[i*s.setLen : (i+1)*s.setLen]
  37. }
  38. // all returns an iterator over the ids in s, in ascending order.
  39. func (s ruleSet) all() iter.Seq[int] {
  40. return func(yield func(int) bool) {
  41. for i, ids := range s {
  42. for ids != 0 {
  43. id := i*8 + bits.TrailingZeros8(ids)
  44. ids &= ids - 1 // Clear the lowest set bit, which is id's.
  45. if !yield(id) {
  46. return
  47. }
  48. }
  49. }
  50. }
  51. }