// io.EOF is returned if the source terminates cleanly on a message boundary.
func (d *Decoder) Decode(msg *Message) (err error) {
var length Integer
- err = binary.Read(d.R, binary.BigEndian, &length)
+ err = length.ReadFrom(d.R)
if err != nil {
- if err != io.EOF {
- err = fmt.Errorf("error reading message length: %w", err)
- }
- return
+ return fmt.Errorf("reading message length: %w", err)
}
if length > d.MaxLength {
return errors.New("message too long")
var m Message
require.NoError(t, d.Decode(&m))
assert.Len(t, m.Piece, 1)
- assert.Equal(t, io.EOF, d.Decode(&m))
+ assert.ErrorIs(t, d.Decode(&m), io.EOF)
}
func TestDecodeOverlongPiece(t *testing.T) {
return i.Read(bytes.NewReader(b))
}
+func (i *Integer) ReadFrom(r io.Reader) error {
+ var b [4]byte
+ n, err := r.Read(b[:])
+ if n == 4 {
+ *i = Integer(binary.BigEndian.Uint32(b[:]))
+ return nil
+ }
+ if err == nil {
+ return io.ErrUnexpectedEOF
+ }
+ return err
+}
+
// It's perfectly fine to cast these to an int. TODO: Or is it?
func (i Integer) Int() int {
return int(i)