Repository: square/okhttp
File: okhttp/src/commonJvmAndroid/kotlin/okhttp3/Cache.kt (Kotlin)

Code before:
    private val bodySource: BufferedSource

    init {
      val source = snapshot.getSource(ENTRY_BODY)
      bodySource =
        object : ForwardingSource(source) {
          @Throws(IOException::class)
          override fun close() {
            snapshot.close()
            super.close()
          }
        }.buffer()
    }

    override fun contentType(): MediaType? = contentType?.toMediaTypeOrNull()

    override fun contentLength(): Long = contentLength?.toLongOrDefault(-1L) ?: -1L

    override fun source(): BufferedSource = bodySource
  }

  companion object {
    private const val VERSION = 201105
    private const val ENTRY_METADATA = 0
    private const val ENTRY_BODY = 1
    private const val ENTRY_COUNT = 2

    @JvmStatic
    fun key(url: HttpUrl): String =
      url
        .toString()
        .encodeUtf8()
        .md5()
        .hex()

    internal fun key(request: Request): String =
      if (
        request.method == "QUERY" &&
        request.body != null &&
        !request.body.isOneShot()
      ) {
        key(request.url) + "_" + Buffer().also { request.body.writeTo(it) }.md5().hex()
      } else {
        // Reading this kind of body would consume it, so we can't cache it.
        key(request.url)
      }

    @Throws(IOException::class)
    internal fun readInt(source: BufferedSource): Int {
      try {
        val result = source.readDecimalLong()

Review comment (performance):
I think this logic needs to consider whether a `Request.cacheUrlOverride` is set. 

See https://github.com/square/okhttp/blob/363d3e788f497dbee0a2bb9762e69f85c4f79d16/okhttp/src/commonJvmAndroid/kotlin/okhttp3/internal/cache/CacheInterceptor.kt#L299

Perhaps that logic should move into here?

Code after:
    }

    override fun contentType(): MediaType? = contentType?.toMediaTypeOrNull()

    override fun contentLength(): Long = contentLength?.toLongOrDefault(-1L) ?: -1L

    override fun source(): BufferedSource = bodySource
  }

  companion object {
    private const val VERSION = 201105
    private const val ENTRY_METADATA = 0
    private const val ENTRY_BODY = 1
    private const val ENTRY_COUNT = 2

    @JvmStatic
    fun key(url: HttpUrl): String =
      url
        .toString()
        .encodeUtf8()
        .md5()
        .hex()

    /** Returns the cache key for a request */
    internal fun key(request: Request): String {
      if (
        // Request such as PUT, DELETE that invalidates a GET
        !HttpMethod.invalidatesCache(request.method) &&

        // QUERY request that considers the request body in the cache key
        HttpMethod.isCacheable(request.method) &&
        HttpMethod.permitsRequestBody(request.method) &&
        request.body != null
      ) {
        val hashingSink = HashingSink.md5(blackholeSink())
        hashingSink.buffer().use {
          it.writeUtf8(request.method)
          it.writeByte(0)
          it.writeUtf8(request.url.toString())
          it.writeByte(0)
          request.body.writeTo(it)
        }
        return hashingSink.hash.hex()
      }

      return request.url
        .toString()
        .encodeUtf8()
        .md5()
        .hex()
    }