Skip to content

Commit ede1faf

Browse files
authored
Inline Digest and Xof.Utils functions (#98)
1 parent 9b73373 commit ede1faf

File tree

7 files changed

+89
-61
lines changed

7 files changed

+89
-61
lines changed

benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/DigestOps.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16+
@file:Suppress("unused")
17+
1618
package org.kotlincrypto.core.benchmarks
1719

1820
import kotlinx.benchmark.*

benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16+
@file:Suppress("unused")
17+
1618
package org.kotlincrypto.core.benchmarks
1719

1820
import kotlinx.benchmark.*
1921
import org.kotlincrypto.core.InternalKotlinCryptoApi
2022
import org.kotlincrypto.core.xof.Xof
21-
import kotlin.random.Random
2223

2324
@State(Scope.Benchmark)
2425
@BenchmarkMode(Mode.AverageTime)
@@ -28,18 +29,18 @@ import kotlin.random.Random
2829
@OptIn(InternalKotlinCryptoApi::class)
2930
open class XofUtilsBenchmark {
3031

31-
private val longs: LongArray = LongArray(10) { Random.Default.nextLong() }
32-
private val loHi = Array(longs.size) { longs[it].let { l -> l.toInt() to l.rotateLeft(32).toInt() } }
32+
@Benchmark
33+
fun leftEncodeLong() {
34+
Xof.Utils.leftEncode(-99993873488683833L)
35+
}
3336

3437
@Benchmark
35-
fun leftEncodeLongs() {
36-
val longs = longs
37-
longs.forEach { long -> Xof.Utils.leftEncode(long) }
38+
fun leftEncodeInt() {
39+
Xof.Utils.leftEncode( 11978435)
3840
}
3941

4042
@Benchmark
4143
fun leftEncodeLoHi() {
42-
val loHi = loHi
43-
loHi.forEach { Xof.Utils.leftEncode(it.first, it.second) }
44+
Xof.Utils.leftEncode(184581845, 11978435)
4445
}
4546
}

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ POM_DEVELOPER_ID=KotlinCrypto
3030
POM_DEVELOPER_NAME=Kotlin Crypto
3131
POM_DEVELOPER_URL=https://github.com/KotlinCrypto/
3232

33-
VERSION_NAME=1.0.0-alpha01-SNAPSHOT
33+
VERSION_NAME=0.6.0-SNAPSHOT
3434
# 0.1.0-alpha01 = 00 01 00 11
3535
# 0.1.0-beta01 = 00 01 00 21
3636
# 0.1.0-rc01 = 00 01 00 31
3737
# 0.1.0 = 00 01 00 99
3838
# 1.1.0 = 01 01 00 99
39-
VERSION_CODE=01000011
39+
VERSION_CODE=00060011

library/digest/src/commonMain/kotlin/org/kotlincrypto/core/digest/internal/-Buffer.kt

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,37 +13,32 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16-
@file:Suppress("KotlinRedundantDiagnosticSuppress")
16+
@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE")
1717

1818
package org.kotlincrypto.core.digest.internal
1919

20+
import org.kotlincrypto.core.digest.Digest
2021
import kotlin.jvm.JvmInline
21-
import kotlin.jvm.JvmSynthetic
2222

2323
@JvmInline
24-
internal value class Buffer private constructor(internal val value: ByteArray) {
25-
26-
internal fun copy(): Buffer = Buffer(value.copyOf())
27-
28-
internal companion object {
29-
30-
@JvmSynthetic
31-
@Throws(IllegalArgumentException::class)
32-
internal fun initialize(
33-
algorithm: String,
34-
blockSize: Int,
35-
digestLength: Int,
36-
): Buffer {
37-
require(algorithm.isNotBlank()) { "algorithm cannot be blank" }
38-
require(blockSize > 0) { "blockSize must be greater than 0" }
39-
require(blockSize % 8 == 0) { "blockSize must be a factor of 8" }
40-
require(digestLength >= 0) { "digestLength cannot be negative" }
41-
return Buffer(ByteArray(blockSize))
42-
}
43-
}
24+
internal value class Buffer internal constructor(internal val value: ByteArray)
25+
26+
@Throws(IllegalArgumentException::class)
27+
@Suppress("UnusedReceiverParameter")
28+
internal inline fun Digest.initializeBuffer(
29+
algorithm: String,
30+
blockSize: Int,
31+
digestLength: Int,
32+
): Buffer {
33+
require(algorithm.isNotBlank()) { "algorithm cannot be blank" }
34+
require(blockSize > 0) { "blockSize must be greater than 0" }
35+
require(blockSize % 8 == 0) { "blockSize must be a factor of 8" }
36+
require(digestLength >= 0) { "digestLength cannot be negative" }
37+
return Buffer(ByteArray(blockSize))
4438
}
4539

46-
@Suppress("NOTHING_TO_INLINE")
40+
internal inline fun Buffer.copy(): Buffer = Buffer(value.copyOf())
41+
4742
internal inline fun Buffer.commonUpdate(
4843
input: Byte,
4944
bufPosPlusPlus: Int,
@@ -59,7 +54,6 @@ internal inline fun Buffer.commonUpdate(
5954
bufPosSet(0)
6055
}
6156

62-
@Suppress("NOTHING_TO_INLINE")
6357
internal inline fun Buffer.commonUpdate(
6458
input: ByteArray,
6559
offset: Int,
@@ -111,20 +105,31 @@ internal inline fun Buffer.commonUpdate(
111105
bufPosSet(posBuf)
112106
}
113107

114-
@Suppress("NOTHING_TO_INLINE")
108+
internal inline fun Buffer.commonDigest(
109+
input: ByteArray,
110+
updateProtected: (ByteArray, Int, Int) -> Unit,
111+
bufPosGet: () -> Int,
112+
digestProtected: (buf: ByteArray, bufPos: Int) -> ByteArray,
113+
resetProtected: () -> Unit,
114+
bufPosSet: (zero: Int) -> Unit,
115+
): ByteArray {
116+
updateProtected(input, 0, input.size)
117+
return commonDigest(bufPosGet(), digestProtected, resetProtected, bufPosSet)
118+
}
119+
115120
internal inline fun Buffer.commonDigest(
116121
bufPos: Int,
117122
digestProtected: (buf: ByteArray, bufPos: Int) -> ByteArray,
118-
reset: () -> Unit,
123+
resetProtected: () -> Unit,
124+
bufPosSet: (zero: Int) -> Unit,
119125
): ByteArray {
120126
// Zeroize any stale input that may be left in the buffer
121127
value.fill(0, bufPos)
122-
val final = digestProtected(value, bufPos)
123-
reset()
124-
return final
128+
val digest = digestProtected(value, bufPos)
129+
commonReset(resetProtected, bufPosSet)
130+
return digest
125131
}
126132

127-
@Suppress("NOTHING_TO_INLINE")
128133
internal inline fun Buffer.commonReset(
129134
resetProtected: () -> Unit,
130135
bufPosSet: (zero: Int) -> Unit,

library/digest/src/jvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public actual abstract class Digest: MessageDigest, Algorithm, Cloneable, Copyab
5757
* */
5858
@Throws(IllegalArgumentException::class)
5959
protected actual constructor(algorithm: String, blockSize: Int, digestLength: Int): super(algorithm) {
60-
this.buf = Buffer.initialize(algorithm, blockSize, digestLength)
60+
this.buf = initializeBuffer(algorithm, blockSize, digestLength)
6161
this.digestLength = digestLength
6262
this.bufPos = 0
6363
}
@@ -127,22 +127,30 @@ public actual abstract class Digest: MessageDigest, Algorithm, Cloneable, Copyab
127127
public actual final override fun digest(): ByteArray = buf.commonDigest(
128128
bufPos = bufPos,
129129
digestProtected = ::digestProtected,
130-
reset = ::reset
130+
resetProtected = ::resetProtected,
131+
bufPosSet = { bufPos = it },
131132
)
132133

133134
/**
134135
* Updates the instance with provided [input], then completes the computation,
135136
* performing final operations and returning the resultant array of bytes. The
136137
* [Digest] is [reset] afterward.
137138
* */
138-
public actual final override fun digest(input: ByteArray): ByteArray {
139-
updateProtected(input, 0, input.size)
140-
return digest()
141-
}
139+
public actual final override fun digest(input: ByteArray): ByteArray = buf.commonDigest(
140+
input = input,
141+
updateProtected = ::updateProtected,
142+
bufPosGet = ::bufPos,
143+
digestProtected = ::digestProtected,
144+
resetProtected = ::resetProtected,
145+
bufPosSet = { bufPos = it },
146+
)
142147

143148
// See Resettable interface documentation
144149
public actual final override fun reset() {
145-
buf.commonReset(::resetProtected) { bufPos = it }
150+
buf.commonReset(
151+
resetProtected = ::resetProtected,
152+
bufPosSet = { bufPos = it },
153+
)
146154
}
147155

148156
/**

library/digest/src/nonJvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public actual abstract class Digest: Algorithm, Copyable<Digest>, Resettable, Up
5252
* */
5353
@Throws(IllegalArgumentException::class)
5454
protected actual constructor(algorithm: String, blockSize: Int, digestLength: Int) {
55-
this.buf = Buffer.initialize(algorithm, blockSize, digestLength)
55+
this.buf = initializeBuffer(algorithm, blockSize, digestLength)
5656
this.algorithm = algorithm
5757
this.digestLength = digestLength
5858
this.bufPos = 0
@@ -124,22 +124,30 @@ public actual abstract class Digest: Algorithm, Copyable<Digest>, Resettable, Up
124124
public actual fun digest(): ByteArray = buf.commonDigest(
125125
bufPos = bufPos,
126126
digestProtected = ::digestProtected,
127-
reset = ::reset,
127+
resetProtected = ::resetProtected,
128+
bufPosSet = { bufPos = it },
128129
)
129130

130131
/**
131132
* Updates the instance with provided [input], then completes the computation,
132133
* performing final operations and returning the resultant array of bytes. The
133134
* [Digest] is [reset] afterward.
134135
* */
135-
public actual fun digest(input: ByteArray): ByteArray {
136-
updateProtected(input, 0, input.size)
137-
return digest()
138-
}
136+
public actual fun digest(input: ByteArray): ByteArray = buf.commonDigest(
137+
input = input,
138+
updateProtected = ::updateProtected,
139+
bufPosGet = ::bufPos,
140+
digestProtected = ::digestProtected,
141+
resetProtected = ::resetProtected,
142+
bufPosSet = { bufPos = it },
143+
)
139144

140145
// See Resettable interface documentation
141146
public actual final override fun reset() {
142-
buf.commonReset(::resetProtected) { bufPos = it }
147+
buf.commonReset(
148+
resetProtected = ::resetProtected,
149+
bufPosSet = { bufPos = it },
150+
)
143151
}
144152

145153
/**

library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
**/
16+
@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE")
17+
1618
package org.kotlincrypto.core.xof
1719

1820
import org.kotlincrypto.core.*
@@ -209,9 +211,7 @@ public sealed class Xof<A: XofAlgorithm>: Algorithm, Copyable<Xof<A>>, Resettabl
209211

210212
@JvmStatic
211213
public fun leftEncode(value: Long): ByteArray {
212-
val lo = value.toInt()
213-
val hi = value.rotateLeft(32).toInt()
214-
return encode(lo = lo, hi = hi, left = true)
214+
return encode(lo = value.lo(), hi = value.hi(), left = true)
215215
}
216216

217217
@JvmStatic
@@ -226,9 +226,7 @@ public sealed class Xof<A: XofAlgorithm>: Algorithm, Copyable<Xof<A>>, Resettabl
226226

227227
@JvmStatic
228228
public fun rightEncode(value: Long): ByteArray {
229-
val lo = value.toInt()
230-
val hi = value.rotateLeft(32).toInt()
231-
return encode(lo = lo, hi = hi, left = false)
229+
return encode(lo = value.lo(), hi = value.hi(), left = false)
232230
}
233231

234232
@JvmStatic
@@ -237,7 +235,13 @@ public sealed class Xof<A: XofAlgorithm>: Algorithm, Copyable<Xof<A>>, Resettabl
237235
}
238236

239237
@JvmStatic
240-
private fun encode(lo: Int, hi: Int, left: Boolean): ByteArray {
238+
private inline fun Long.lo(): Int = toInt()
239+
240+
@JvmStatic
241+
private inline fun Long.hi(): Int = rotateLeft(32).toInt()
242+
243+
@JvmStatic
244+
private inline fun encode(lo: Int, hi: Int, left: Boolean): ByteArray {
241245
val a = if (hi == 0) {
242246
if (lo == 0) {
243247
// If it's zero, return early

0 commit comments

Comments
 (0)