-
Notifications
You must be signed in to change notification settings - Fork 2
/
hex.go
67 lines (60 loc) · 1.51 KB
/
hex.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package mutators
import (
"bufio"
"encoding/hex"
"io"
"github.com/batmac/ccat/pkg/log"
)
func init() {
singleRegister("hexdump", hexDump, withDescription("dump in hex as xxd"), withHintLexer("hexdump"))
singleRegister("hex", hexRaw, withDescription("dump in lowercase hex"),
withCategory("convert"))
singleRegister("unhex", unhex, withDescription("decode hex, ignore all non-hex chars"),
withCategory("convert"))
}
func hexDump(w io.WriteCloser, r io.ReadCloser, _ any) (int64, error) {
dumper := hex.Dumper(w)
n, err := io.Copy(dumper, r) // streamable
log.Debugf("finished\n")
defer dumper.Close()
return n, err
}
func hexRaw(w io.WriteCloser, r io.ReadCloser, _ any) (int64, error) {
h := hex.NewEncoder(w)
return io.Copy(h, r) // streamable
}
func unhex(w io.WriteCloser, r io.ReadCloser, _ any) (int64, error) {
rp, wp := io.Pipe()
decoder := hex.NewDecoder(rp)
go func() {
scanner := bufio.NewScanner(r)
scanner.Split(bufio.ScanRunes)
for scanner.Scan() {
chars := scanner.Bytes()
// log.Debugf("scan %v", chars)
if len(chars) == 1 {
if isBase16Char(chars[0]) {
// log.Debugf("base16 %c", chars[0])
_, _ = wp.Write(chars)
}
}
}
if err := scanner.Err(); err != nil {
log.Println("unhexing input:", err)
}
_ = wp.Close()
}()
return io.Copy(w, decoder) // streamable
}
func isBase16Char(c byte) bool {
switch {
case c >= '0' && c <= '9':
return true
case c >= 'A' && c <= 'F':
return true
case c >= 'a' && c <= 'f':
return true
default:
return false
}
}