summaryrefslogtreecommitdiffstats
path: root/xdr/reader.go
blob: bad58324bcb2a5f6dc4834bdf57f10ac7097fb89 (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package xdr

import (
	"errors"
	"io"
)

var ErrElementSizeExceeded = errors.New("element size exceeded")

type Reader struct {
	r   io.Reader
	tot int
	err error
	b   [8]byte
}

func NewReader(r io.Reader) *Reader {
	return &Reader{
		r: r,
	}
}

func (r *Reader) ReadString() string {
	return string(r.ReadBytes())
}

func (r *Reader) ReadStringMax(max int) string {
	return string(r.ReadBytesMax(max))
}

func (r *Reader) ReadBytes() []byte {
	return r.ReadBytesInto(nil)
}

func (r *Reader) ReadBytesMax(max int) []byte {
	return r.ReadBytesMaxInto(max, nil)
}

func (r *Reader) ReadBytesInto(dst []byte) []byte {
	return r.ReadBytesMaxInto(0, dst)
}

func (r *Reader) ReadBytesMaxInto(max int, dst []byte) []byte {
	if r.err != nil {
		return nil
	}
	l := int(r.ReadUint32())
	if r.err != nil {
		return nil
	}
	if max > 0 && l > max {
		r.err = ErrElementSizeExceeded
		return nil
	}
	if l+pad(l) > len(dst) {
		dst = make([]byte, l+pad(l))
	} else {
		dst = dst[:l+pad(l)]
	}
	var n int
	n, r.err = io.ReadFull(r.r, dst)
	r.tot += n
	if debug {
		if n > maxDebugBytes {
			dl.Debugf("rd bytes (%d): %x...", n, dst[:maxDebugBytes])
		} else {
			dl.Debugf("rd bytes (%d): %x", n, dst)
		}
	}
	return dst[:l]
}

func (r *Reader) ReadUint16() uint16 {
	if r.err != nil {
		return 0
	}
	_, r.err = io.ReadFull(r.r, r.b[:4])
	r.tot += 4
	v := uint16(r.b[1]) | uint16(r.b[0])<<8
	if debug {
		dl.Debugf("rd uint16=%d", v)
	}
	return v
}

func (r *Reader) ReadUint32() uint32 {
	var n int
	if r.err != nil {
		return 0
	}
	n, r.err = io.ReadFull(r.r, r.b[:4])
	if n < 4 {
		return 0
	}
	r.tot += n
	v := uint32(r.b[3]) | uint32(r.b[2])<<8 | uint32(r.b[1])<<16 | uint32(r.b[0])<<24
	if debug {
		dl.Debugf("rd uint32=%d", v)
	}
	return v
}

func (r *Reader) ReadUint64() uint64 {
	var n int
	if r.err != nil {
		return 0
	}
	n, r.err = io.ReadFull(r.r, r.b[:8])
	r.tot += n
	v := uint64(r.b[7]) | uint64(r.b[6])<<8 | uint64(r.b[5])<<16 | uint64(r.b[4])<<24 |
		uint64(r.b[3])<<32 | uint64(r.b[2])<<40 | uint64(r.b[1])<<48 | uint64(r.b[0])<<56
	if debug {
		dl.Debugf("rd uint64=%d", v)
	}
	return v
}

func (r *Reader) Tot() int {
	return r.tot
}

func (r *Reader) Error() error {
	return r.err
}