code: func ReadMessage(r io.Reader, s ws.State, m []Message) ([]Message, error) {
  	rd := Reader{
  		Source:    r,
  		State:     s,
  		CheckUTF8: true,
  		OnIntermediate: func(hdr ws.Header, src io.Reader) error {
  			bts, err := ioutil.ReadAll(src)
  			if err != nil {
  				return err
  			}
  			m = append(m, Message{hdr.OpCode, bts})
  			return nil
  		},
  	}
  	h, err := rd.NextFrame()
  	if err != nil {
  		return m, err
  	}
  	var p []byte
  	if h.Fin {
  		// No more frames will be read. Use fixed sized buffer to read payload.
  		p = make([]byte, h.Length)
  		// It is not possible to receive io.EOF here because Reader does not
  		// return EOF if frame payload was successfuly fetched.
  		// Thus we consistent here with io.Reader behavior.
  		_, err = io.ReadFull(&rd, p)
  	} else {
  		// Frame is fragmented, thus use ioutil.ReadAll behavior.
  		var buf bytes.Buffer
  		_, err = buf.ReadFrom(&rd)
  		p = buf.Bytes()
  	}
  	if err != nil {
  		return m, err
  	}
  	return append(m, Message{h.OpCode, p}), nil
  }
docs: // ReadMessage is a helper function that reads next message from r. It appends
  // received message(s) to the third argument and returns the result of it and
  // an error if some failure happened. That is, it probably could receive more
  // than one message when peer sending fragmented message in multiple frames and
  // want to send some control frame between fragments. Then returned slice will
  // contain those control frames at first, and then result of gluing fragments.
  //
  // TODO(gobwas): add DefaultReader with buffer size options.