main

square/leakcanary

Last updated at: 29/12/2023 09:38

ThrowingCancelableFileSourceProvider.kt

TLDR

The ThrowingCancelableFileSourceProvider class in the shark package is a DualSourceProvider that allows cancellation of IO based work by throwing an exception before every read operation.

Classes

DualSourceProvider

The DualSourceProvider interface is implemented by the ThrowingCancelableFileSourceProvider class. It is a provider that offers both streaming and random access sources.

Methods

None

package shark

import java.io.File
import java.io.IOException
import okio.Buffer
import okio.BufferedSource
import okio.Okio
import okio.Source

/**
 * A [DualSourceProvider] that invokes [throwIfCanceled] before every read, allowing
 * cancellation of IO based work built on top by throwing an exception.
 */
class ThrowingCancelableFileSourceProvider(
  private val file: File,
  private val throwIfCanceled: Runnable
) : DualSourceProvider {

  override fun openStreamingSource(): BufferedSource {
    val realSource = Okio.source(file.inputStream())
    return Okio.buffer(object : Source by realSource {
      override fun read(
        sink: Buffer,
        byteCount: Long
      ): Long {
        throwIfCanceled.run()
        return realSource.read(sink, byteCount)
      }
    })
  }

  override fun openRandomAccessSource(): RandomAccessSource {
    val channel = file.inputStream().channel
    return object : RandomAccessSource {
      override fun read(
        sink: Buffer,
        position: Long,
        byteCount: Long
      ): Long {
        throwIfCanceled.run()
        return channel.transferTo(position, byteCount, sink)
      }

      override fun close() {
        try {
          channel.close()
        } catch (ignored: Throwable) {
          SharkLog.d(ignored) { "Failed to close file, ignoring" }
        }
      }
    }
  }
}