3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-23 19:22:41 +01:00
ergo/irc/caps/set.go

145 lines
3.2 KiB
Go
Raw Normal View History

// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package caps
import (
2019-08-27 06:51:09 +02:00
"bytes"
"sort"
"github.com/oragono/oragono/irc/utils"
)
// Set holds a set of enabled capabilities.
type Set [bitsetLen]uint32
2019-08-27 06:51:09 +02:00
// Values holds capability values.
type Values map[Capability]string
// NewSet returns a new Set, with the given capabilities enabled.
func NewSet(capabs ...Capability) *Set {
var newSet Set
newSet.Enable(capabs...)
return &newSet
}
// NewCompleteSet returns a new Set, with all defined capabilities enabled.
func NewCompleteSet() *Set {
var newSet Set
asSlice := newSet[:]
for i := 0; i < numCapabs; i += 1 {
utils.BitsetSet(asSlice, uint(i), true)
}
return &newSet
}
// Enable enables the given capabilities.
func (s *Set) Enable(capabs ...Capability) {
asSlice := s[:]
for _, capab := range capabs {
utils.BitsetSet(asSlice, uint(capab), true)
}
}
// Disable disables the given capabilities.
func (s *Set) Disable(capabs ...Capability) {
asSlice := s[:]
for _, capab := range capabs {
utils.BitsetSet(asSlice, uint(capab), false)
}
}
// Add adds the given capabilities to this set.
// this is just a wrapper to allow more clear use.
func (s *Set) Add(capabs ...Capability) {
s.Enable(capabs...)
}
// Remove removes the given capabilities from this set.
// this is just a wrapper to allow more clear use.
func (s *Set) Remove(capabs ...Capability) {
s.Disable(capabs...)
}
// Has returns true if this set has the given capability.
func (s *Set) Has(capab Capability) bool {
return utils.BitsetGet(s[:], uint(capab))
}
// HasAll returns true if the set has all the given capabilities.
func (s *Set) HasAll(capabs ...Capability) bool {
for _, capab := range capabs {
if !s.Has(capab) {
return false
}
}
return true
}
// Union adds all the capabilities of another set to this set.
func (s *Set) Union(other *Set) {
utils.BitsetUnion(s[:], other[:])
}
// Subtract removes all the capabilities of another set from this set.
func (s *Set) Subtract(other *Set) {
utils.BitsetSubtract(s[:], other[:])
}
// Empty returns whether the set is empty.
func (s *Set) Empty() bool {
return utils.BitsetEmpty(s[:])
}
2019-08-27 06:51:09 +02:00
const maxPayloadLength = 440
2019-09-08 12:22:34 +02:00
// Strings returns all of our enabled capabilities as a slice of strings.
func (s *Set) Strings(version Version, values Values) (result []string) {
var strs sort.StringSlice
var capab Capability
asSlice := s[:]
for capab = 0; capab < numCapabs; capab++ {
// skip any capabilities that are not enabled
if !utils.BitsetGet(asSlice, uint(capab)) {
continue
}
capString := capab.Name()
2019-09-08 12:22:34 +02:00
if version >= Cap302 {
2019-08-27 06:51:09 +02:00
val, exists := values[capab]
if exists {
capString += "=" + val
}
}
strs = append(strs, capString)
}
2019-08-27 06:51:09 +02:00
if len(strs) == 0 {
return []string{""}
}
// sort the cap string before we send it out
sort.Sort(strs)
2019-08-27 06:51:09 +02:00
var buf bytes.Buffer
for _, str := range strs {
tokenLen := len(str)
if buf.Len() != 0 {
tokenLen += 1
}
if maxPayloadLength < buf.Len()+tokenLen {
result = append(result, buf.String())
buf.Reset()
}
if buf.Len() != 0 {
buf.WriteByte(' ')
}
buf.WriteString(str)
}
if buf.Len() != 0 {
result = append(result, buf.String())
}
return
}