docs: def read_header(self, source = None):
          '''
          Reads and parses message header.
          
          .. note:: :func:`.read_header` wraps data for further reading in internal
                    buffer  
      
          :Parameters:
           - `source` - optional data buffer to be read, if not specified data is 
             read from the wrapped stream
             
          :returns: :class:`.QMessage` - read meta information
          '''
          if self._stream:
              header = self._read_bytes(8)
              self._buffer.wrap(header)
          else:
              self._buffer.wrap(source)
  
          self._buffer.endianness = '<' if self._buffer.get_byte() == 1 else '>'
          self._is_native = self._buffer.endianness == ('<' if sys.byteorder == 'little' else '>')
          message_type = self._buffer.get_byte()
          message_compressed = self._buffer.get_byte() == 1
          # skip 1 byte
          self._buffer.skip()
  
          message_size = self._buffer.get_int()
          return QMessage(None, message_type, message_size, message_compressed)