/**
     * Reads an entry from an input stream. A typical entry looks like this:
     *
     * <pre>{@code
     * http://google.com/foo
     * GET
     * 2
     * Accept-Language: fr-CA
     * Accept-Charset: UTF-8
     * HTTP/1.1 200 OK
     * 3
     * Content-Type: image/png
     * Content-Length: 100
     * Cache-Control: max-age=600
     * }</pre>
     *
     * <p>A typical HTTPS file looks like this:
     *
     * <pre>{@code
     * https://google.com/foo
     * GET
     * 2
     * Accept-Language: fr-CA
     * Accept-Charset: UTF-8
     * HTTP/1.1 200 OK
     * 3
     * Content-Type: image/png
     * Content-Length: 100
     * Cache-Control: max-age=600
     *
     * AES_256_WITH_MD5
     * 2
     * base64-encoded peerCertificate[0]
     * base64-encoded peerCertificate[1]
     * -1
     * }</pre>
     *
     * The file is newline separated. The first two lines are the URL and the request method. Next
     * is the number of HTTP Vary request header lines, followed by those lines.
     *
     * <p>Next is the response status line, followed by the number of HTTP response header lines,
     * followed by those lines.
     *
     * <p>HTTPS responses also contain SSL session information. This begins with a blank line, and
     * then a line containing the cipher suite. Next is the length of the peer certificate chain.
     * These certificates are base64-encoded and appear each on their own line. The next line
     * contains the length of the local certificate chain. These certificates are also
     * base64-encoded and appear each on their own line. A length of -1 is used to encode a null
     * array.
     */
    public Entry(Source in) throws IOException {
      try {
        BufferedSource source = Okio.buffer(in);
        url = source.readUtf8LineStrict();
        requestMethod = source.readUtf8LineStrict();
        if (readInt(source) == 1) {
          MediaType contentType = MediaType.parse(source.readUtf8LineStrict());
          int contentLength = readInt(source);
          requestBody = RequestBody.create(contentType, source.readByteArray(contentLength));
        } else {
          requestBody = null;
        }
        Headers.Builder varyHeadersBuilder = new Headers.Builder();
        int varyRequestHeaderLineCount = readInt(source);
        for (int i = 0; i < varyRequestHeaderLineCount; i++) {
          OkHttpAccess.addLenient(varyHeadersBuilder, source.readUtf8LineStrict());
        }
        varyHeaders = varyHeadersBuilder.build();

        StatusLine statusLine = StatusLine.parse(source.readUtf8LineStrict());
        protocol = statusLine.protocol;
        code = statusLine.code;
        message = statusLine.message;
        Headers.Builder responseHeadersBuilder = new Headers.Builder();
        int responseHeaderLineCount = readInt(source);
        for (int i = 0; i < responseHeaderLineCount; i++) {
          OkHttpAccess.addLenient(responseHeadersBuilder, source.readUtf8LineStrict());
        }
        responseHeaders = responseHeadersBuilder.build();

        if (isHttps()) {
          String blank = source.readUtf8LineStrict();
          if (blank.length() > 0) {
            throw new IOException("expected \"\" but was \"" + blank + "\"");
          }
          String cipherSuite = source.readUtf8LineStrict();
          List<Certificate> peerCertificates = readCertificateList(source);
          List<Certificate> localCertificates = readCertificateList(source);
          handshake = Handshake.get(cipherSuite, peerCertificates, localCertificates);
        } else {
          handshake = null;
        }
      } finally {
        in.close();
      }
    }
 private Response response(DiskLruCache.Snapshot snapshot) throws IOException {
   String contentType = responseHeaders.get("Content-Type");
   Request cacheRequest =
       new Request.Builder()
           .url(url)
           .method(requestMethod, requestBody)
           .headers(varyHeaders)
           .build();
   BufferedSource source = Okio.buffer(snapshot.getSource(RESPONSE_BODY));
   byte[] bodyContent = source.readByteArray();
   MediaType mediaType = contentType == null ? null : MediaType.parse(contentType);
   return new Response.Builder()
       .request(cacheRequest)
       .protocol(protocol)
       .code(code)
       .message(message)
       .headers(responseHeaders)
       .body(new OkHttpUtil.ReusableResponseBody(mediaType, bodyContent))
       .handshake(handshake)
       .build();
 }