frame.go
func (f *Frame) ReadBody(header []byte, r io.Reader) error {
	// Copy the header into the underlying buffer so we have an assembled frame
	// that can be directly forwarded.
	copy(f.buffer, header)

	// Parse the header into our typed struct.
	if err := f.Header.read(typed.NewReadBuffer(header)); err != nil {
		return err
	}

	switch payloadSize := f.Header.PayloadSize(); {
	case payloadSize > MaxFramePayloadSize:
		return fmt.Errorf("invalid frame size %v", f.Header.size)
	case payloadSize > 0:
		_, err := io.ReadFull(r, f.SizedPayload())
		return err
	default:
		// No payload to read
		return nil
	}
}
func (f *Frame) ReadBody(header []byte, r io.Reader) error {
	// Copy the header into the underlying buffer so we have an assembled frame
	// that can be directly forwarded.
	copy(f.buffer, header)

	// Parse the header into our typed struct.
	if err := f.Header.read(typed.NewReadBuffer(header)); err != nil {
		return err
	}

	switch payloadSize := f.Header.PayloadSize(); {
	case payloadSize > MaxFramePayloadSize:
		return fmt.Errorf("invalid frame size %v", f.Header.size)
	case payloadSize > 0:
		_, err := io.ReadFull(r, f.SizedPayload())
		return err
	default:
		// No payload to read
		return nil
	}
}
// ReadBody takes in a previously read frame header, and only reads in the body
// based on the size specified in the header. This allows callers to defer
// the frame allocation till the body needs to be read.