diff --git a/library/xof/api/xof.api b/library/xof/api/xof.api index 1c0652c..3d50cca 100644 --- a/library/xof/api/xof.api +++ b/library/xof/api/xof.api @@ -17,7 +17,7 @@ public abstract class org/kotlincrypto/core/xof/Xof$Reader { public final fun isClosed ()Z public final fun read ([B)I public final fun read ([BII)I - protected abstract fun readProtected ([BIIJ)V + protected abstract fun readProtected ([BII)I public final fun toString ()Ljava/lang/String; public final fun use (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } diff --git a/library/xof/api/xof.klib.api b/library/xof/api/xof.klib.api index 32ace1c..1295b16 100644 --- a/library/xof/api/xof.klib.api +++ b/library/xof/api/xof.klib.api @@ -40,13 +40,14 @@ sealed class <#A: org.kotlincrypto.core.xof/XofAlgorithm> org.kotlincrypto.core. abstract inner class Reader { // org.kotlincrypto.core.xof/Xof.Reader|null[0] constructor () // org.kotlincrypto.core.xof/Xof.Reader.|(){}[0] - final var bytesRead // org.kotlincrypto.core.xof/Xof.Reader.bytesRead|{}bytesRead[0] + final val bytesRead // org.kotlincrypto.core.xof/Xof.Reader.bytesRead|{}bytesRead[0] final fun (): kotlin/Long // org.kotlincrypto.core.xof/Xof.Reader.bytesRead.|(){}[0] + final var isClosed // org.kotlincrypto.core.xof/Xof.Reader.isClosed|{}isClosed[0] final fun (): kotlin/Boolean // org.kotlincrypto.core.xof/Xof.Reader.isClosed.|(){}[0] abstract fun closeProtected() // org.kotlincrypto.core.xof/Xof.Reader.closeProtected|closeProtected(){}[0] - abstract fun readProtected(kotlin/ByteArray, kotlin/Int, kotlin/Int, kotlin/Long) // org.kotlincrypto.core.xof/Xof.Reader.readProtected|readProtected(kotlin.ByteArray;kotlin.Int;kotlin.Int;kotlin.Long){}[0] + abstract fun readProtected(kotlin/ByteArray, kotlin/Int, kotlin/Int): kotlin/Int // org.kotlincrypto.core.xof/Xof.Reader.readProtected|readProtected(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] final fun <#A2: kotlin/Any?> use(kotlin/Function1, #A2>): #A2 // org.kotlincrypto.core.xof/Xof.Reader.use|use(kotlin.Function1,0:0>){0ยง}[0] final fun close() // org.kotlincrypto.core.xof/Xof.Reader.close|close(){}[0] final fun read(kotlin/ByteArray): kotlin/Int // org.kotlincrypto.core.xof/Xof.Reader.read|read(kotlin.ByteArray){}[0] diff --git a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt index c62a52f..7379c1f 100644 --- a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt +++ b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt @@ -100,12 +100,22 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl * */ public abstract inner class Reader { + private var lo: Int = 0 + private var hi: Int = 0 + /** - * The total amount of bytes read for this [Reader] instance + * The total amount of bytes read for this [Reader] instance. + * + * **NOTE:** Only tracks up to a maximum of 2^64 bytes. Actual + * output can potentially be larger than that. * */ @get:JvmName("bytesRead") - public var bytesRead: Long = 0 - private set + public val bytesRead: Long get() { + val lo = lo + val hi = hi + if (hi == 0) return lo.toLong() + return ((hi.toLong() and 0xffffffff) shl 32) or (lo.toLong() and 0xffffffff) + } /** * If the reader is closed or not @@ -159,9 +169,14 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl if (len == 0) return 0 if (offset < 0 || len < 0 || offset > out.size - len) throw IndexOutOfBoundsException() - readProtected(out, offset, len, bytesRead) - bytesRead += len - return len + val read = readProtected(out, offset, len) + + // Update read counter + val lt0 = lo < 0 + lo += read + if (lt0 && lo >= 0) hi++ + + return read } /** @@ -177,16 +192,14 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl isClosed = true } + protected abstract fun readProtected(out: ByteArray, offset: Int, len: Int): Int protected abstract fun closeProtected() - protected abstract fun readProtected(out: ByteArray, offset: Int, len: Int, bytesRead: Long) + /** @suppress */ public final override fun toString(): String = "${this@Xof}.Reader@${hashCode()}" } - protected abstract fun newReader(): Reader - - public final override fun toString(): String = "Xof[${algorithm()}]@${hashCode()}" - + /** @suppress */ @InternalKotlinCryptoApi public object Utils { @@ -236,4 +249,10 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl return b } } + + protected abstract fun newReader(): Reader + + /** @suppress */ + public final override fun toString(): String = "Xof[${algorithm()}]@${hashCode()}" + } diff --git a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/XofFactory.kt b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/XofFactory.kt index ddc2760..96f968e 100644 --- a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/XofFactory.kt +++ b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/XofFactory.kt @@ -55,7 +55,7 @@ public abstract class XofFactory public constructor() { protected abstract inner class XofDelegate @Throws(ClassCastException::class, IllegalArgumentException::class) protected constructor( - protected val delegate: A + protected val delegate: A, ) : Xof(), Algorithm by delegate, Resettable by delegate as Resettable, @@ -78,9 +78,11 @@ public abstract class XofFactory public constructor() { * */ protected abstract fun newReader(delegateCopy: A): Reader + /** @suppress */ public final override fun equals(other: Any?): Boolean { return other is XofFactory<*>.XofDelegate && other.delegate == delegate } + /** @suppress */ public final override fun hashCode(): Int = delegate.hashCode() } }