kinds.go raw

   1  // Package kinds is a set of helpers for dealing with lists of kind numbers
   2  // including comparisons and encoding.
   3  package kind
   4  
   5  import (
   6  	"next.orly.dev/pkg/nostr/encoders/ints"
   7  	"next.orly.dev/pkg/lol/chk"
   8  	"next.orly.dev/pkg/lol/errorf"
   9  )
  10  
  11  // S is an array of kind.K, used in filter.K and filter.S for searches.
  12  type S struct {
  13  	K []*K
  14  }
  15  
  16  // NewS creates a new kinds.S, if no parameter is given it just creates an empty zero kinds.S.
  17  func NewS(k ...*K) *S { return &S{k} }
  18  
  19  // NewWithCap creates a new empty kinds.S with a given slice capacity.
  20  func NewWithCap(c int) *S { return &S{make([]*K, 0, c)} }
  21  
  22  // FromIntSlice converts a []int into a kinds.S.
  23  func FromIntSlice(is []int) (k *S) {
  24  	k = &S{}
  25  	for i := range is {
  26  		k.K = append(k.K, New(uint16(is[i])))
  27  	}
  28  	return
  29  }
  30  
  31  // Len returns the number of elements in a kinds.S.
  32  func (k *S) Len() (l int) {
  33  	if k == nil {
  34  		return
  35  	}
  36  	return len(k.K)
  37  }
  38  
  39  // Less returns which of two elements of a kinds.S is lower.
  40  func (k *S) Less(i, j int) bool { return k.K[i].K < k.K[j].K }
  41  
  42  // Swap switches the position of two kinds.S elements.
  43  func (k *S) Swap(i, j int) {
  44  	k.K[i].K, k.K[j].K = k.K[j].K, k.K[i].K
  45  }
  46  
  47  // ToUint16 returns a []uint16 version of the kinds.S.
  48  func (k *S) ToUint16() (o []uint16) {
  49  	for i := range k.K {
  50  		o = append(o, k.K[i].ToU16())
  51  	}
  52  	return
  53  }
  54  
  55  // Clone makes a new kind.K with the same members.
  56  func (k *S) Clone() (c *S) {
  57  	c = &S{K: make([]*K, len(k.K))}
  58  	for i := range k.K {
  59  		c.K[i] = k.K[i]
  60  	}
  61  	return
  62  }
  63  
  64  // Contains returns true if the provided element is found in the kinds.S.
  65  //
  66  // Note that the request must use the typed kind.K or convert the number thus.
  67  // Even if a custom number is found, this codebase does not have the logic to
  68  // deal with the kind so such a search is pointless and for which reason static
  69  // typing always wins. No mistakes possible with known quantities.
  70  func (k *S) Contains(s uint16) bool {
  71  	for i := range k.K {
  72  		if k.K[i].Equal(s) {
  73  			return true
  74  		}
  75  	}
  76  	return false
  77  }
  78  
  79  // Equals checks that the provided kind.K matches.
  80  func (k *S) Equals(t1 *S) bool {
  81  	if len(k.K) != len(t1.K) {
  82  		return false
  83  	}
  84  	for i := range k.K {
  85  		if k.K[i] != t1.K[i] {
  86  			return false
  87  		}
  88  	}
  89  	return true
  90  }
  91  
  92  // Marshal renders the kinds.S into a JSON array of integers.
  93  func (k *S) Marshal(dst []byte) (b []byte) {
  94  	b = dst
  95  	b = append(b, '[')
  96  	for i := range k.K {
  97  		b = k.K[i].Marshal(b)
  98  		if i != len(k.K)-1 {
  99  			b = append(b, ',')
 100  		}
 101  	}
 102  	b = append(b, ']')
 103  	return
 104  }
 105  
 106  // Unmarshal decodes a provided JSON array of integers into a kinds.S.
 107  func (k *S) Unmarshal(b []byte) (r []byte, err error) {
 108  	r = b
 109  	var openedBracket bool
 110  	for ; len(r) > 0; r = r[1:] {
 111  		if !openedBracket && r[0] == '[' {
 112  			openedBracket = true
 113  			continue
 114  		} else if openedBracket {
 115  			if r[0] == ']' {
 116  				// done
 117  				return
 118  			} else if r[0] == ',' {
 119  				continue
 120  			}
 121  			kk := ints.New(0)
 122  			if r, err = kk.Unmarshal(r); chk.E(err) {
 123  				return
 124  			}
 125  			k.K = append(k.K, New(kk.Uint16()))
 126  			if r[0] == ']' {
 127  				r = r[1:]
 128  				return
 129  			}
 130  		}
 131  	}
 132  	if !openedBracket {
 133  		return nil, errorf.E(
 134  			"kinds: failed to unmarshal\n%s\n%s\n%s", k,
 135  			b, r,
 136  		)
 137  	}
 138  	return
 139  }
 140  
 141  // IsPrivileged returns true if any of the elements of a kinds.S are privileged (ie, they should
 142  // be privacy protected).
 143  func (k *S) IsPrivileged() (priv bool) {
 144  	for i := range k.K {
 145  		if IsPrivileged(k.K[i].K) {
 146  			return true
 147  		}
 148  	}
 149  	return
 150  }
 151