1 package shark 2 3 import java.io.File 4 import java.io.IOException 5 import okio.Buffer 6 import okio.BufferedSource 7 import okio.Okio 8 import okio.Source 9 10 /** 11 * A [DualSourceProvider] that invokes [throwIfCanceled] before every read, allowing 12 * cancellation of IO based work built on top by throwing an exception. 13 */ 14 class ThrowingCancelableFileSourceProvider( 15 private val file: File, 16 private val throwIfCanceled: Runnable 17 ) : DualSourceProvider { 18 openStreamingSourcenull19 override fun openStreamingSource(): BufferedSource { 20 val realSource = Okio.source(file.inputStream()) 21 return Okio.buffer(object : Source by realSource { 22 override fun read( 23 sink: Buffer, 24 byteCount: Long 25 ): Long { 26 throwIfCanceled.run() 27 return realSource.read(sink, byteCount) 28 } 29 }) 30 } 31 openRandomAccessSourcenull32 override fun openRandomAccessSource(): RandomAccessSource { 33 val channel = file.inputStream().channel 34 return object : RandomAccessSource { 35 override fun read( 36 sink: Buffer, 37 position: Long, 38 byteCount: Long 39 ): Long { 40 throwIfCanceled.run() 41 return channel.transferTo(position, byteCount, sink) 42 } 43 44 override fun close() { 45 try { 46 channel.close() 47 } catch (ignored: Throwable) { 48 SharkLog.d(ignored) { "Failed to close file, ignoring" } 49 } 50 } 51 } 52 } 53 } 54