Skip to content

Commit 9a2475d

Browse files
authored
feat: add 'BitSet' viewer (#503)
1 parent 551c4d3 commit 9a2475d

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

backend/types/view_type.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const FORMAT_YAML = "YAML"
77
const FORMAT_XML = "XML"
88
const FORMAT_HEX = "Hex"
99
const FORMAT_BINARY = "Binary"
10+
const FORMAT_BITSET = "BitSet"
1011

1112
const DECODE_NONE = "None"
1213
const DECODE_BASE64 = "Base64"
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package convutil
2+
3+
import (
4+
"fmt"
5+
"math"
6+
"strconv"
7+
"strings"
8+
)
9+
10+
type BitSetConvert struct{}
11+
12+
func (BitSetConvert) Enable() bool {
13+
return true
14+
}
15+
16+
func (BitSetConvert) Encode(str string) (string, bool) {
17+
var result strings.Builder
18+
19+
str = strings.ReplaceAll(str, "\r\n", "\n") // CRLF → LF
20+
str = strings.ReplaceAll(str, "\r", "\n") // CR → LF
21+
22+
lines := strings.Split(str, "\n")
23+
bytes := EncodeToRedisBitset(lines)
24+
result.Write(bytes)
25+
26+
return result.String(), true
27+
}
28+
29+
// EncodeToRedisBitset encodes a list of strings with integers (positions) into a Redis bitset byte array.
30+
// The bit at position 'n' will be set to 1 if n is in the input array.
31+
// The resulting byte slice can be stored in Redis using SET command.
32+
func EncodeToRedisBitset(numbers []string) []byte {
33+
if len(numbers) == 0 {
34+
return []byte{}
35+
}
36+
37+
// Find the maximum number to determine the required bit length and convert strings to numbers
38+
maxNum := uint64(0)
39+
var validNumbers []uint64
40+
for _, s := range numbers {
41+
if s == "" {
42+
continue
43+
}
44+
num, err := strconv.ParseUint(s, 10, 64)
45+
if err != nil || num < 0 || num > math.MaxUint32 {
46+
fmt.Printf("Warning: skipping invalid number '%s': %v\n", s, err)
47+
continue
48+
}
49+
validNumbers = append(validNumbers, num)
50+
if num > maxNum {
51+
maxNum = num
52+
}
53+
}
54+
55+
if len(validNumbers) == 0 {
56+
return []byte{}
57+
}
58+
59+
// Calculate required byte length (8 bits per byte)
60+
byteLen := ((maxNum + 7) / 8) + 1
61+
62+
// Initialize byte array
63+
bitset := make([]byte, byteLen)
64+
65+
// Set bits for each number
66+
for _, num := range validNumbers {
67+
byteIndex := num / 8
68+
if byteIndex < byteLen {
69+
bitIndex := uint(num % 8)
70+
// Set the bit (big-endian bit order within byte)
71+
bitset[byteIndex] |= 1 << (7 - bitIndex)
72+
}
73+
}
74+
75+
return bitset
76+
}
77+
78+
func (BitSetConvert) Decode(str string) (string, bool) {
79+
bitset := getBitSet([]byte(str))
80+
81+
var binBuilder strings.Builder
82+
for key, value := range bitset {
83+
if value {
84+
binBuilder.WriteString(fmt.Sprintf("%v\n", key))
85+
//binBuilder.WriteString(fmt.Sprintf("Bit %v = %v \n", key, value))
86+
}
87+
}
88+
89+
return binBuilder.String(), true
90+
}
91+
92+
func getBitSet(redisResponse []byte) []bool {
93+
bitset := make([]bool, len(redisResponse)*8)
94+
for i := range redisResponse {
95+
for j := 7; j >= 0; j-- {
96+
bit_n := uint(i*8 + (7 - j))
97+
bitset[bit_n] = (redisResponse[i] & (1 << uint(j))) > 0
98+
}
99+
}
100+
return bitset
101+
}

backend/utils/convert/convert.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var (
2020
xmlConv XmlConvert
2121
base64Conv Base64Convert
2222
binaryConv BinaryConvert
23+
bitSetConv BitSetConvert
2324
hexConv HexConvert
2425
gzipConv GZipConvert
2526
deflateConv DeflateConvert
@@ -38,6 +39,7 @@ var BuildInFormatters = map[string]DataConvert{
3839
types.FORMAT_XML: xmlConv,
3940
types.FORMAT_HEX: hexConv,
4041
types.FORMAT_BINARY: binaryConv,
42+
types.FORMAT_BITSET: bitSetConv,
4143
}
4244

4345
var BuildInDecoders = map[string]DataConvert{

frontend/src/consts/value_view_type.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const formatTypes = {
1010
XML: 'XML',
1111
HEX: 'Hex',
1212
BINARY: 'Binary',
13+
BITSET: 'BitSet',
1314
}
1415

1516
/**

0 commit comments

Comments
 (0)