Expose bencode.Decoder.Offset

This commit is contained in:
Matt Joiner 2017-11-05 15:42:37 +11:00
parent 2c6b842bbf
commit edf2495b1f
2 changed files with 29 additions and 29 deletions

View File

@ -17,7 +17,7 @@ type Decoder struct {
io.ByteScanner io.ByteScanner
io.Reader io.Reader
} }
offset int64 Offset int64
buf bytes.Buffer buf bytes.Buffer
key string key string
} }
@ -38,7 +38,7 @@ func (d *Decoder) Decode(v interface{}) (err error) {
} }
if !d.parseValue(pv.Elem()) { if !d.parseValue(pv.Elem()) {
d.throwSyntaxError(d.offset-1, errors.New("unexpected 'e'")) d.throwSyntaxError(d.Offset-1, errors.New("unexpected 'e'"))
} }
return nil return nil
} }
@ -55,11 +55,11 @@ func checkForUnexpectedEOF(err error, offset int64) {
func (d *Decoder) readByte() byte { func (d *Decoder) readByte() byte {
b, err := d.r.ReadByte() b, err := d.r.ReadByte()
if err != nil { if err != nil {
checkForUnexpectedEOF(err, d.offset) checkForUnexpectedEOF(err, d.Offset)
panic(err) panic(err)
} }
d.offset++ d.Offset++
return b return b
} }
@ -93,7 +93,7 @@ func (d *Decoder) throwSyntaxError(offset int64, err error) {
// called when 'i' was consumed // called when 'i' was consumed
func (d *Decoder) parseInt(v reflect.Value) { func (d *Decoder) parseInt(v reflect.Value) {
start := d.offset - 1 start := d.Offset - 1
d.readUntil('e') d.readUntil('e')
if d.buf.Len() == 0 { if d.buf.Len() == 0 {
panic(&SyntaxError{ panic(&SyntaxError{
@ -139,7 +139,7 @@ func (d *Decoder) parseInt(v reflect.Value) {
} }
func (d *Decoder) parseString(v reflect.Value) { func (d *Decoder) parseString(v reflect.Value) {
start := d.offset - 1 start := d.Offset - 1
// read the string length first // read the string length first
d.readUntil(':') d.readUntil(':')
@ -148,11 +148,11 @@ func (d *Decoder) parseString(v reflect.Value) {
d.buf.Reset() d.buf.Reset()
n, err := io.CopyN(&d.buf, d.r, length) n, err := io.CopyN(&d.buf, d.r, length)
d.offset += n d.Offset += n
if err != nil { if err != nil {
checkForUnexpectedEOF(err, d.offset) checkForUnexpectedEOF(err, d.Offset)
panic(&SyntaxError{ panic(&SyntaxError{
Offset: d.offset, Offset: d.Offset,
What: errors.New("unexpected I/O error: " + err.Error()), What: errors.New("unexpected I/O error: " + err.Error()),
}) })
} }
@ -339,7 +339,7 @@ func (d *Decoder) readOneValue() bool {
d.r.UnreadByte() d.r.UnreadByte()
return false return false
} else { } else {
d.offset++ d.Offset++
d.buf.WriteByte(b) d.buf.WriteByte(b)
} }
@ -359,22 +359,22 @@ func (d *Decoder) readOneValue() bool {
start := d.buf.Len() - 1 start := d.buf.Len() - 1
d.readUntil(':') d.readUntil(':')
length, err := strconv.ParseInt(d.buf.String()[start:], 10, 64) length, err := strconv.ParseInt(d.buf.String()[start:], 10, 64)
checkForIntParseError(err, d.offset-1) checkForIntParseError(err, d.Offset-1)
d.buf.WriteString(":") d.buf.WriteString(":")
n, err := io.CopyN(&d.buf, d.r, length) n, err := io.CopyN(&d.buf, d.r, length)
d.offset += n d.Offset += n
if err != nil { if err != nil {
checkForUnexpectedEOF(err, d.offset) checkForUnexpectedEOF(err, d.Offset)
panic(&SyntaxError{ panic(&SyntaxError{
Offset: d.offset, Offset: d.Offset,
What: errors.New("unexpected I/O error: " + err.Error()), What: errors.New("unexpected I/O error: " + err.Error()),
}) })
} }
break break
} }
d.raiseUnknownValueType(b, d.offset-1) d.raiseUnknownValueType(b, d.Offset-1)
} }
return true return true
@ -435,7 +435,7 @@ func (d *Decoder) parseValue(v reflect.Value) bool {
if err != nil { if err != nil {
panic(err) panic(err)
} }
d.offset++ d.Offset++
switch b { switch b {
case 'e': case 'e':
@ -455,7 +455,7 @@ func (d *Decoder) parseValue(v reflect.Value) bool {
break break
} }
d.raiseUnknownValueType(b, d.offset-1) d.raiseUnknownValueType(b, d.Offset-1)
} }
return true return true
@ -474,7 +474,7 @@ func (d *Decoder) parseValueInterface() (interface{}, bool) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
d.offset++ d.Offset++
switch b { switch b {
case 'e': case 'e':
@ -493,13 +493,13 @@ func (d *Decoder) parseValueInterface() (interface{}, bool) {
return d.parseStringInterface(), true return d.parseStringInterface(), true
} }
d.raiseUnknownValueType(b, d.offset-1) d.raiseUnknownValueType(b, d.Offset-1)
panic("unreachable") panic("unreachable")
} }
} }
func (d *Decoder) parseIntInterface() (ret interface{}) { func (d *Decoder) parseIntInterface() (ret interface{}) {
start := d.offset - 1 start := d.Offset - 1
d.readUntil('e') d.readUntil('e')
if d.buf.Len() == 0 { if d.buf.Len() == 0 {
panic(&SyntaxError{ panic(&SyntaxError{
@ -529,7 +529,7 @@ func (d *Decoder) parseIntInterface() (ret interface{}) {
} }
func (d *Decoder) parseStringInterface() interface{} { func (d *Decoder) parseStringInterface() interface{} {
start := d.offset - 1 start := d.Offset - 1
// read the string length first // read the string length first
d.readUntil(':') d.readUntil(':')
@ -538,11 +538,11 @@ func (d *Decoder) parseStringInterface() interface{} {
d.buf.Reset() d.buf.Reset()
n, err := io.CopyN(&d.buf, d.r, length) n, err := io.CopyN(&d.buf, d.r, length)
d.offset += n d.Offset += n
if err != nil { if err != nil {
checkForUnexpectedEOF(err, d.offset) checkForUnexpectedEOF(err, d.Offset)
panic(&SyntaxError{ panic(&SyntaxError{
Offset: d.offset, Offset: d.Offset,
What: errors.New("unexpected I/O error: " + err.Error()), What: errors.New("unexpected I/O error: " + err.Error()),
}) })
} }
@ -563,7 +563,7 @@ func (d *Decoder) parseDictInterface() interface{} {
key, ok := keyi.(string) key, ok := keyi.(string)
if !ok { if !ok {
panic(&SyntaxError{ panic(&SyntaxError{
Offset: d.offset, Offset: d.Offset,
What: errors.New("non-string key in a dict"), What: errors.New("non-string key in a dict"),
}) })
} }

View File

@ -75,7 +75,7 @@ func TestDecoderConsecutiveDicts(t *testing.T) {
d := NewDecoder(bb) d := NewDecoder(bb)
assert.EqualValues(t, "d4:herp4:derped3:wat1:ke17:oh baby a triple!", bb.Bytes()) assert.EqualValues(t, "d4:herp4:derped3:wat1:ke17:oh baby a triple!", bb.Bytes())
assert.EqualValues(t, 0, d.offset) assert.EqualValues(t, 0, d.Offset)
var m map[string]interface{} var m map[string]interface{}
@ -83,17 +83,17 @@ func TestDecoderConsecutiveDicts(t *testing.T) {
assert.Len(t, m, 1) assert.Len(t, m, 1)
assert.Equal(t, "derp", m["herp"]) assert.Equal(t, "derp", m["herp"])
assert.Equal(t, "d3:wat1:ke17:oh baby a triple!", bb.String()) assert.Equal(t, "d3:wat1:ke17:oh baby a triple!", bb.String())
assert.EqualValues(t, 14, d.offset) assert.EqualValues(t, 14, d.Offset)
require.NoError(t, d.Decode(&m)) require.NoError(t, d.Decode(&m))
assert.Equal(t, "k", m["wat"]) assert.Equal(t, "k", m["wat"])
assert.Equal(t, "17:oh baby a triple!", bb.String()) assert.Equal(t, "17:oh baby a triple!", bb.String())
assert.EqualValues(t, 24, d.offset) assert.EqualValues(t, 24, d.Offset)
var s string var s string
require.NoError(t, d.Decode(&s)) require.NoError(t, d.Decode(&s))
assert.Equal(t, "oh baby a triple!", s) assert.Equal(t, "oh baby a triple!", s)
assert.EqualValues(t, 44, d.offset) assert.EqualValues(t, 44, d.Offset)
} }
func check_error(t *testing.T, err error) { func check_error(t *testing.T, err error) {