<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _ReadCacheEntry(self, file_object, display_name, block_size):
 """Reads a cache entry. Args: file_object (dfvfs.FileIO):
 a file-like object. display_name (str):
 display name. block_size (int):
 block size. Returns: tuple: containing: firefox_cache1_entry_header: cache record header structure. FirefoxCacheEventData: event data. Raises: IOError: if the cache record header cannot be validated. OSError: if the cache record header cannot be validated. ParseError: if the cache record header cannot be parsed. """

    file_offset = file_object.get_offset()

    # TODO: merge reading the cache entry header and body by having dtFabric
    # implement the sanity checks done in _ValidateCacheEntryHeader.

    # Seeing that this parser tries to read each block for a possible
    # cache entry, we read the fixed-size values first.
    cache_entry_header_map = self._GetDataTypeMap('firefox_cache1_entry_header')

    try:
      cache_entry_header, header_data_size = self._ReadStructureFromFileObject(
          file_object, file_offset, cache_entry_header_map)
    except (ValueError, errors.ParseError) as exception:
      raise errors.ParseError(
          'Unable to parse Firefox cache entry header with error: {0!s}'.format(
              exception))

    if not self._ValidateCacheEntryHeader(cache_entry_header):
      # Skip to the next block potentially containing a cache entry.
      file_offset = block_size - header_data_size
      file_object.seek(file_offset, os.SEEK_CUR)
      raise IOError('Not a valid Firefox cache record.')

    body_data_size = (
        cache_entry_header.request_size + cache_entry_header.information_size)

    cache_entry_body_data = self._ReadData(
        file_object, file_offset + header_data_size, body_data_size)

    url = cache_entry_body_data[:cache_entry_header.request_size].decode(
        'ascii').rstrip('\x00')
    request_method, response_code = self._ParseHTTPHeaders(
        cache_entry_body_data[cache_entry_header.request_size:], file_offset,
        display_name)

    # A request can span multiple blocks, so we use modulo.
    cache_entry_data_size = header_data_size + body_data_size
    _, remaining_data_size = divmod(cache_entry_data_size, block_size)
    if remaining_data_size > 0:
      file_object.seek(block_size - remaining_data_size, os.SEEK_CUR)

    event_data = FirefoxCacheEventData()
    event_data.data_size = cache_entry_header.cached_data_size
    event_data.fetch_count = cache_entry_header.fetch_count
    event_data.info_size = cache_entry_header.information_size
    event_data.location = cache_entry_header.location
    event_data.request_method = request_method
    event_data.request_size = cache_entry_header.request_size
    event_data.response_code = response_code
    event_data.url = url
    event_data.version = '{0:d}.{1:d}'.format(
        cache_entry_header.major_format_version,
        cache_entry_header.minor_format_version)

    return cache_entry_header, event_data