Files
orly/pkg/encoders/kinds/kinds.go
mleku dda39de5a5
Some checks failed
Go / build (push) Has been cancelled
Go / release (push) Has been cancelled
refactor logging to use closures for intensive tasks
2025-08-15 22:27:16 +01:00

152 lines
3.4 KiB
Go

// Package kinds is a set of helpers for dealing with lists of kind numbers
// including comparisons and encoding.
package kinds
import (
"orly.dev/pkg/encoders/ints"
"orly.dev/pkg/encoders/kind"
"orly.dev/pkg/utils/chk"
"orly.dev/pkg/utils/errorf"
)
// T is an array of kind.T, used in filter.T and filter.S for searches.
type T struct {
K []*kind.T
}
// New creates a new kinds.T, if no parameter is given it just creates an empty zero kinds.T.
func New(k ...*kind.T) *T { return &T{k} }
// NewWithCap creates a new empty kinds.T with a given slice capacity.
func NewWithCap(c int) *T { return &T{make([]*kind.T, 0, c)} }
// FromIntSlice converts a []int into a kinds.T.
func FromIntSlice(is []int) (k *T) {
k = &T{}
for i := range is {
k.K = append(k.K, kind.New(uint16(is[i])))
}
return
}
// Len returns the number of elements in a kinds.T.
func (k *T) Len() (l int) {
if k == nil {
return
}
return len(k.K)
}
// Less returns which of two elements of a kinds.T is lower.
func (k *T) Less(i, j int) bool { return k.K[i].K < k.K[j].K }
// Swap switches the position of two kinds.T elements.
func (k *T) Swap(i, j int) {
k.K[i].K, k.K[j].K = k.K[j].K, k.K[i].K
}
// ToUint16 returns a []uint16 version of the kinds.T.
func (k *T) ToUint16() (o []uint16) {
for i := range k.K {
o = append(o, k.K[i].ToU16())
}
return
}
// Clone makes a new kind.T with the same members.
func (k *T) Clone() (c *T) {
c = &T{K: make([]*kind.T, len(k.K))}
for i := range k.K {
c.K[i] = k.K[i]
}
return
}
// Contains returns true if the provided element is found in the kinds.T.
//
// Note that the request must use the typed kind.T or convert the number thus.
// Even if a custom number is found, this codebase does not have the logic to
// deal with the kind so such a search is pointless and for which reason static
// typing always wins. No mistakes possible with known quantities.
func (k *T) Contains(s *kind.T) bool {
for i := range k.K {
if k.K[i].Equal(s) {
return true
}
}
return false
}
// Equals checks that the provided kind.T matches.
func (k *T) Equals(t1 *T) bool {
if len(k.K) != len(t1.K) {
return false
}
for i := range k.K {
if k.K[i] != t1.K[i] {
return false
}
}
return true
}
// Marshal renders the kinds.T into a JSON array of integers.
func (k *T) Marshal(dst []byte) (b []byte) {
b = dst
b = append(b, '[')
for i := range k.K {
b = k.K[i].Marshal(b)
if i != len(k.K)-1 {
b = append(b, ',')
}
}
b = append(b, ']')
return
}
// Unmarshal decodes a provided JSON array of integers into a kinds.T.
func (k *T) Unmarshal(b []byte) (r []byte, err error) {
r = b
var openedBracket bool
for ; len(r) > 0; r = r[1:] {
if !openedBracket && r[0] == '[' {
openedBracket = true
continue
} else if openedBracket {
if r[0] == ']' {
// done
return
} else if r[0] == ',' {
continue
}
kk := ints.New(0)
if r, err = kk.Unmarshal(r); chk.E(err) {
return
}
k.K = append(k.K, kind.New(kk.Uint16()))
if r[0] == ']' {
r = r[1:]
return
}
}
}
if !openedBracket {
return nil, errorf.E(
"kinds: failed to unmarshal\n%s\n%s\n%s", k,
b, r,
)
}
return
}
// IsPrivileged returns true if any of the elements of a kinds.T are privileged (ie, they should
// be privacy protected).
func (k *T) IsPrivileged() (priv bool) {
for i := range k.K {
if k.K[i].IsPrivileged() {
return true
}
}
return
}