summaryrefslogtreecommitdiff
path: root/rrdformat/errors_binary.go
blob: 7329927b76284f460d086af65b061afdc2d5f521 (plain)
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
68
69
70
71
72
73
74
75
package rrdformat

import (
	"fmt"
	"io"
)

type BinaryError struct {
	msg    string
	ctxPos int
	ctxDat []byte
	ctxEOF bool
}

func newBinError(msg string, ctxFile []byte, ctxStart, ctxLen int) error {
	if ctxStart+ctxLen > len(ctxFile) {
		ctxLen = len(ctxFile) - ctxStart
	}
	return BinaryError{
		msg:    msg,
		ctxPos: ctxStart,
		ctxDat: ctxFile[ctxStart : ctxStart+ctxLen],
		ctxEOF: ctxStart+ctxLen == len(ctxFile),
	}
}

func (e BinaryError) Error() string {
	return "invalid RRD: " + e.msg
}

var cAsciiEscapes = map[byte]byte{
	0x00: '0',
	0x07: 'a',
	0x08: 'b',
	0x09: 't',
	0x0A: 'n',
	0x0B: 'v',
	0x0C: 'f',
	0x0D: 'r',
}

func (e BinaryError) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		io.WriteString(s, e.Error())
		if s.Flag('+') {
			fmt.Fprintf(s, "\n\tat byte %d:", e.ctxPos)
			io.WriteString(s, "\n\t\tascii:")
			for _, byte := range e.ctxDat {
				if ' ' <= byte && byte <= '~' {
					fmt.Fprintf(s, "  %c", byte)
				} else if c, ok := cAsciiEscapes[byte]; ok {
					fmt.Fprintf(s, " \\%c", c)
				} else {
					io.WriteString(s, " ??")
				}
			}
			if e.ctxEOF {
				io.WriteString(s, " <EOF>")
			}
			io.WriteString(s, "\n\t\thex  :")
			for _, byte := range e.ctxDat {
				fmt.Fprintf(s, " %02x", byte)
			}
			if e.ctxEOF {
				io.WriteString(s, " <EOF>")
			}
			io.WriteString(s, "\n")
		}
	case 's':
		io.WriteString(s, e.Error())
	case 'q':
		fmt.Fprintf(s, "%q", e.Error())
	}
}