feat: super 包新增比特掩码类型 BitMask,可通过 super.Mask 函数创建。该类型可替代 super.Permission

This commit is contained in:
kercylan98 2023-12-13 17:07:57 +08:00
parent 8a8610f756
commit 38cc3129ba
2 changed files with 112 additions and 0 deletions

96
utils/super/mask.go Normal file
View File

@ -0,0 +1,96 @@
package super
import (
"github.com/kercylan98/minotaur/utils/generic"
"math/bits"
"strconv"
)
// BitMask 使用泛型类型 Bit 表示一个比特掩码Bit 必须是整数类型。
type BitMask[Bit generic.Integer] uint64
// Mask 创建一个新的 BitMask包含给定的比特位。
// 参数 bits 是一个可变参数列表,表示要设置的比特位。
// - 使用按位或运算符 (|=) 将 bit 位置的比特设置为 1。
func Mask[Bit generic.Integer](bits ...Bit) BitMask[Bit] {
var mask Bit
for _, bit := range bits {
mask |= 1 << bit
}
return BitMask[Bit](mask)
}
// Matches 检查当前 BitMask 是否与另一个 BitMask 完全匹配。
func (slf *BitMask[Bit]) Matches(bits BitMask[Bit]) bool {
return *slf == bits
}
// Contains 检查当前 BitMask 是否包含另一个 BitMask。
// - 使用按位与运算符 (&) 计算两个 BitMask 的公共部分,然后与 bits 进行比较。
func (slf *BitMask[Bit]) Contains(bits BitMask[Bit]) bool {
return (*slf & bits) == bits
}
// Has 检查当前 BitMask 是否包含特定的比特位。
// - 使用按位与运算符 (&) 检查 bit 位置的比特是否为 1。
func (slf *BitMask[Bit]) Has(bits ...Bit) bool {
for _, bit := range bits {
if *slf&(1<<bit) == 0 {
return false
}
}
return true
}
// Add 将给定的比特位添加到当前 BitMask 中。
// - 使用按位或运算符 (|=) 将 bit 位置的比特设置为 1。
func (slf *BitMask[Bit]) Add(bit Bit) {
*slf |= 1 << bit
}
// Del 从当前 BitMask 中删除给定的比特位。
// - 使用按位与运算符 (&) 取反 (^) 然后按位与运算符 (&) 清除 bit 位置的比特。
func (slf *BitMask[Bit]) Del(bit Bit) {
*slf &= ^(1 << bit)
}
// Toggle 反转指定比特位。
// - 使用按位或运算符 (|=) 将 bit 位置的比特设置为 1如果 bit 位置的比特已经为 1则使用按位与运算符 (&^=) 将 bit 位置的比特设置为 0。
func (slf *BitMask[Bit]) Toggle(bit Bit) {
*slf ^= 1 << bit
}
// Reset 将当前 BitMask 重置为 all 0。
func (slf *BitMask[Bit]) Reset() {
*slf = 0
}
// Count 统计 BitMask 中被设置的比特位数量。
// - 使用按位与运算符 (&) 将 BitMask 与 0xFFFFFFFF 进行按位与运算,然后使用 `bits.Len()` 函数统计 0 的数量。
func (slf *BitMask[Bit]) Count() int {
return 64 - bits.Len64(uint64(*slf)&0xFFFFFFFF)
}
// Union 返回当前 BitMask 和另一个 BitMask 的并集。
// - 使用按位或运算符 (&) 将两个 BitMask 进行合并。
func (slf *BitMask[Bit]) Union(other BitMask[Bit]) BitMask[Bit] {
return *slf | other
}
// Intersection 返回当前 BitMask 和另一个 BitMask 的交集。
// - 使用按位与运算符 (&) 将两个 BitMask 进行交集。
func (slf *BitMask[Bit]) Intersection(other BitMask[Bit]) BitMask[Bit] {
return *slf & other
}
// Difference 返回当前 BitMask 和另一个 BitMask 的差集。
// - 使用按位异或运算符 (^) 将两个 BitMask 进行异或。
func (slf *BitMask[Bit]) Difference(other BitMask[Bit]) BitMask[Bit] {
return *slf ^ other
}
// String 返回当前 BitMask 的字符串表示形式。
// - 使用 `strconv.FormatUint()` 函数将 BitMask 转换为二进制字符串。
func (slf *BitMask[Bit]) String() string {
return strconv.FormatUint(uint64(*slf), 2)
}

16
utils/super/mask_test.go Normal file
View File

@ -0,0 +1,16 @@
package super_test
import (
"github.com/kercylan98/minotaur/utils/super"
"testing"
)
func TestMask(t *testing.T) {
mask := super.Mask(1, 2, 3, 5)
t.Log(mask.Matches(super.Mask(1, 2, 3, 5)))
t.Log(mask.Matches(super.Mask(1, 2, 3, 4, 5)))
t.Log(mask.Matches(super.Mask(1, 2, 5)))
t.Log(mask.Contains(super.Mask(1, 2, 5)))
t.Log(mask)
}