Progress on native generator
This commit is contained in:
parent
c975bdb248
commit
97c631ecb7
@ -72,10 +72,12 @@ data class CustomTypeDefinition(override val typeName: TypeName) : GeneralTypeDe
|
||||
|
||||
enum class TypeDefinition(override val typeName: TypeName) : GeneralTypeDefinition {
|
||||
ARRAY_OF_UBYTES(UByteArray::class.asTypeName()),
|
||||
ARRAY_OF_UBYTES_LONG_SIZE(UByteArray::class.asTypeName()),
|
||||
ARRAY_OF_UBYTES_NO_SIZE(UByteArray::class.asTypeName()),
|
||||
LONG(Long::class.asTypeName()),
|
||||
INT(Int::class.asTypeName()),
|
||||
STRING(String::class.asTypeName())
|
||||
STRING(String::class.asTypeName()),
|
||||
UNIT(Unit::class.asTypeName())
|
||||
}
|
||||
|
||||
fun fileDef(name: String, body: KotlinFileDefinition.() -> Unit) : KotlinFileDefinition {
|
||||
@ -132,33 +134,4 @@ fun funcDef(
|
||||
}
|
||||
|
||||
|
||||
object LibSodiumDefinitions {
|
||||
val testKotlinFile = fileDef("DebugTest") {
|
||||
+classDef("Hashing") {
|
||||
+innerClassDef(
|
||||
"Sha256State",
|
||||
"com.goterl.lazycode.lazysodium.interfaces.Hash.State256",
|
||||
"Sha256State",
|
||||
"crypto_hash_sha256_state"
|
||||
)
|
||||
+funcDef(
|
||||
"crypto_hash_sha256_init",
|
||||
TypeDefinition.INT
|
||||
) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha256State"))))
|
||||
}
|
||||
}
|
||||
|
||||
+classDef("GenericHash") {
|
||||
|
||||
+funcDef(
|
||||
"crypto_generichash_init",
|
||||
TypeDefinition.INT
|
||||
) {
|
||||
+ParameterDefinition("state", TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE)
|
||||
+ParameterDefinition("key", TypeDefinition.ARRAY_OF_UBYTES)
|
||||
+ParameterDefinition("outlen", TypeDefinition.INT, modifiesReturn = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.ionspin.kotlin.crypto.generator.libsodium.definitions
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 01-Aug-2020
|
||||
*/
|
||||
object LibSodiumDefinitions {
|
||||
val testKotlinFile = fileDef("DebugTest") {
|
||||
+classDef("Crypto") {
|
||||
|
||||
/*
|
||||
--------------- SHA256
|
||||
*/
|
||||
+innerClassDef(
|
||||
"Sha256State",
|
||||
"com.goterl.lazycode.lazysodium.interfaces.Hash.State256",
|
||||
"Sha256State",
|
||||
"crypto_hash_sha256_state"
|
||||
)
|
||||
+funcDef(
|
||||
"crypto_hash_sha256_init",
|
||||
TypeDefinition.INT
|
||||
) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha256State"))))
|
||||
}
|
||||
|
||||
+funcDef("crypto_hash_sha256_update", TypeDefinition.UNIT) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha256State"))))
|
||||
+ParameterDefinition("input", TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE)
|
||||
}
|
||||
|
||||
+funcDef("crypto_hash_sha256_final", TypeDefinition.UNIT) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha256State"))))
|
||||
+ParameterDefinition("out", TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE)
|
||||
}
|
||||
|
||||
/*
|
||||
--------------- SHA512
|
||||
*/
|
||||
+innerClassDef(
|
||||
"Sha512State",
|
||||
"com.goterl.lazycode.lazysodium.interfaces.Hash.State512",
|
||||
"Sha512State",
|
||||
"crypto_hash_sha512_state"
|
||||
)
|
||||
+funcDef(
|
||||
"crypto_hash_sha512_init",
|
||||
TypeDefinition.INT
|
||||
) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha512State"))))
|
||||
}
|
||||
|
||||
+funcDef("crypto_hash_sha512_update", TypeDefinition.UNIT) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha512State"))))
|
||||
+ParameterDefinition("input", TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE)
|
||||
}
|
||||
|
||||
+funcDef("crypto_hash_sha512_final", TypeDefinition.UNIT) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha512State"))))
|
||||
+ParameterDefinition("out", TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE)
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------- GENERIC HASH (BLAKE2B)
|
||||
*/
|
||||
|
||||
+innerClassDef(
|
||||
"GenericHashState",
|
||||
"ByteArray",
|
||||
"Uint8Array",
|
||||
"crypto_generichash_blake2b_state"
|
||||
)
|
||||
|
||||
+funcDef(
|
||||
"crypto_generichash_init",
|
||||
TypeDefinition.INT
|
||||
) {
|
||||
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("GenericHashState"))))
|
||||
+ParameterDefinition("key", TypeDefinition.ARRAY_OF_UBYTES)
|
||||
+ParameterDefinition("outlen", TypeDefinition.INT, modifiesReturn = true)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.ionspin.kotlin.crypto.generator.libsodium.generator
|
||||
|
||||
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.LibSodiumDefinitions
|
||||
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.packageName
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@ -10,12 +11,16 @@ import java.io.File
|
||||
*/
|
||||
object Coordinator {
|
||||
|
||||
fun run(packageName: String) {
|
||||
fun run() {
|
||||
|
||||
val commonFileSpec = CommonLibsodiumGenerator.createCommonFile(packageName, LibSodiumDefinitions.testKotlinFile)
|
||||
val jvmFileSpec = JvmLibsodiumGenerator.createJvmFile(packageName, LibSodiumDefinitions.testKotlinFile)
|
||||
val nativeFileSpec = NativeLibsodiumGenerator.createNativeFile(packageName, LibSodiumDefinitions.testKotlinFile)
|
||||
val commonFile = File("multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/")
|
||||
commonFileSpec.writeTo(commonFile)
|
||||
val jvmFile = File("multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/")
|
||||
jvmFileSpec.writeTo(jvmFile)
|
||||
val nativeFile = File("multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/")
|
||||
nativeFileSpec.writeTo(nativeFile)
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ object JvmLibsodiumGenerator {
|
||||
returnModifierName = paramDefinition.parameterName
|
||||
}
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType == TypeDefinition.ARRAY_OF_UBYTES) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
@ -79,6 +80,15 @@ object JvmLibsodiumGenerator {
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType == TypeDefinition.UNIT) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
constructJvmCall.append("sodium.${methodDefinition.javaName}")
|
||||
constructJvmCall.append(paramsToString(methodDefinition))
|
||||
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType is CustomTypeDefinition) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
@ -107,7 +117,10 @@ object JvmLibsodiumGenerator {
|
||||
if (paramDefinition.parameterType is TypeDefinition) {
|
||||
when(paramDefinition.parameterType) {
|
||||
TypeDefinition.ARRAY_OF_UBYTES -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".asByteArray()" + separator + paramDefinition.parameterName + ".size, ")
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".asByteArray(), " + paramDefinition.parameterName + ".size" + separator)
|
||||
}
|
||||
TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".asByteArray(), " + paramDefinition.parameterName + ".size.toLong()" + separator)
|
||||
}
|
||||
TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".asByteArray()" + separator)
|
||||
|
@ -0,0 +1,150 @@
|
||||
package com.ionspin.kotlin.crypto.generator.libsodium.generator
|
||||
|
||||
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.*
|
||||
import com.squareup.kotlinpoet.*
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 31-Jul-2020
|
||||
*/
|
||||
object NativeLibsodiumGenerator {
|
||||
|
||||
|
||||
fun createNativeFile(packageName: String, fileDefinition: KotlinFileDefinition): FileSpec {
|
||||
val fileBuilder = FileSpec.builder(packageName, fileDefinition.name)
|
||||
fileBuilder.addImport("kotlinx.cinterop", "toCValues")
|
||||
fileBuilder.addImport("kotlinx.cinterop", "convert")
|
||||
fileBuilder.addImport("kotlinx.cinterop", "ptr")
|
||||
// val sodiumProperty = PropertySpec.builder("sodium", ClassName.bestGuess("com.goterl.lazycode.lazysodium.SodiumJava"))
|
||||
// sodiumProperty.initializer(CodeBlock.of("SodiumJava()"))
|
||||
// fileBuilder.addProperty(sodiumProperty.build())
|
||||
for (commonClassDefinition in fileDefinition.commonClassList) {
|
||||
//Create type-aliases
|
||||
commonClassDefinition.innerClasses.forEach {
|
||||
fileBuilder.addTypeAlias(createJvmInnerClassSpec(it, MultiplatformModifier.ACTUAL))
|
||||
}
|
||||
|
||||
val commonClassSpec = createClass(
|
||||
commonClassDefinition,
|
||||
MultiplatformModifier.ACTUAL,
|
||||
::createNativeFunctionImplementation
|
||||
)
|
||||
fileBuilder.addType(commonClassSpec)
|
||||
}
|
||||
val file = fileBuilder.build()
|
||||
file.writeTo(System.out)
|
||||
return file
|
||||
}
|
||||
|
||||
fun createJvmInnerClassSpec(
|
||||
innerClassDefinition: InnerClassDefinition,
|
||||
multiplatformModifier: MultiplatformModifier
|
||||
): TypeAliasSpec {
|
||||
val innerClassBuilder =
|
||||
TypeAliasSpec.builder(innerClassDefinition.name, ClassName("libsodium", innerClassDefinition.nativeName))
|
||||
innerClassBuilder.modifiers += multiplatformModifier.modifierList
|
||||
|
||||
return innerClassBuilder.build()
|
||||
}
|
||||
|
||||
fun createNativeFunctionImplementation(methodDefinition: FunctionDefinition): FunSpec {
|
||||
val methodBuilder = FunSpec.builder(methodDefinition.name)
|
||||
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
|
||||
var returnModifierFound = false
|
||||
var returnModifierName = ""
|
||||
for (paramDefinition in methodDefinition.parameterList) {
|
||||
val parameterSpec =
|
||||
ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName)
|
||||
methodBuilder.addParameter(parameterSpec.build())
|
||||
if (paramDefinition.modifiesReturn) {
|
||||
if (returnModifierFound == true) {
|
||||
throw RuntimeException("Return modifier already found")
|
||||
}
|
||||
returnModifierFound = true
|
||||
returnModifierName = paramDefinition.parameterName
|
||||
}
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType == TypeDefinition.ARRAY_OF_UBYTES) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
constructJvmCall.append("return libsodium.${methodDefinition.nativeName}")
|
||||
constructJvmCall.append(paramsToString(methodDefinition))
|
||||
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType == TypeDefinition.INT) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
constructJvmCall.append("return libsodium.${methodDefinition.nativeName}")
|
||||
constructJvmCall.append(paramsToString(methodDefinition))
|
||||
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType == TypeDefinition.UNIT) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
constructJvmCall.append("libsodium.${methodDefinition.nativeName}")
|
||||
constructJvmCall.append(paramsToString(methodDefinition))
|
||||
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
if (methodDefinition.returnType is CustomTypeDefinition) {
|
||||
methodBuilder.addStatement("println(\"Debug\")")
|
||||
val constructJvmCall = StringBuilder()
|
||||
constructJvmCall.append("return libsodium.${methodDefinition.nativeName}")
|
||||
constructJvmCall.append(paramsToString(methodDefinition))
|
||||
|
||||
methodBuilder.addStatement(constructJvmCall.toString())
|
||||
}
|
||||
|
||||
methodBuilder.returns(methodDefinition.returnType.typeName)
|
||||
return methodBuilder.build()
|
||||
}
|
||||
|
||||
fun paramsToString(methodDefinition: FunctionDefinition): String {
|
||||
val paramsBuilder = StringBuilder()
|
||||
paramsBuilder.append("(")
|
||||
methodDefinition.parameterList.forEachIndexed { index, paramDefinition ->
|
||||
val separator = if (index == methodDefinition.parameterList.size - 1) {
|
||||
""
|
||||
} else {
|
||||
", "
|
||||
}
|
||||
if (paramDefinition.parameterType is CustomTypeDefinition) {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".ptr" + separator)
|
||||
}
|
||||
if (paramDefinition.parameterType is TypeDefinition) {
|
||||
when (paramDefinition.parameterType) {
|
||||
TypeDefinition.ARRAY_OF_UBYTES -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".toCValues(), " + paramDefinition.parameterName + ".size.convert()" + separator)
|
||||
}
|
||||
TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".toCValues(), " + paramDefinition.parameterName + ".size.convert()" + separator)
|
||||
}
|
||||
TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".toCValues()" + separator)
|
||||
}
|
||||
TypeDefinition.LONG -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".convert()" + separator)
|
||||
}
|
||||
TypeDefinition.INT -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + ".convert()" + separator)
|
||||
}
|
||||
TypeDefinition.STRING -> {
|
||||
paramsBuilder.append(paramDefinition.parameterName + separator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
paramsBuilder.append(')')
|
||||
return paramsBuilder.toString()
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -11,9 +11,8 @@ import org.junit.Test
|
||||
* on 31-Jul-2020
|
||||
*/
|
||||
class DebugTest {
|
||||
val packageName = "debug.test"
|
||||
@Test
|
||||
fun debugTest() {
|
||||
Coordinator.run(packageName)
|
||||
Coordinator.run()
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,25 @@ import kotlin.UByteArray
|
||||
|
||||
expect class Sha256State
|
||||
|
||||
expect class Hashing {
|
||||
fun crypto_hash_sha256_init(state: Sha256State): Int
|
||||
}
|
||||
expect class Sha512State
|
||||
|
||||
expect class GenericHashState
|
||||
|
||||
expect class Crypto {
|
||||
fun crypto_hash_sha256_init(state: Sha256State): Int
|
||||
|
||||
fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray)
|
||||
|
||||
fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray)
|
||||
|
||||
fun crypto_hash_sha512_init(state: Sha512State): Int
|
||||
|
||||
fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray)
|
||||
|
||||
fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray)
|
||||
|
||||
expect class GenericHash {
|
||||
fun crypto_generichash_init(
|
||||
state: UByteArray,
|
||||
state: GenericHashState,
|
||||
key: UByteArray,
|
||||
outlen: Int
|
||||
): Int
|
||||
|
@ -1,5 +1,6 @@
|
||||
package debug.test
|
||||
|
||||
import ByteArray
|
||||
import com.goterl.lazycode.lazysodium.SodiumJava
|
||||
import com.goterl.lazycode.lazysodium.interfaces.Hash
|
||||
import kotlin.Int
|
||||
@ -9,20 +10,47 @@ val sodium: SodiumJava = SodiumJava()
|
||||
|
||||
actual typealias Sha256State = Hash.State256
|
||||
|
||||
actual class Hashing {
|
||||
actual typealias Sha512State = Hash.State512
|
||||
|
||||
actual typealias GenericHashState = ByteArray
|
||||
|
||||
actual class Crypto {
|
||||
actual fun crypto_hash_sha256_init(state: Sha256State): Int {
|
||||
println("Debug")
|
||||
return sodium.crypto_hash_sha256_init(state)
|
||||
}
|
||||
}
|
||||
|
||||
actual class GenericHash {
|
||||
actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) {
|
||||
println("Debug")
|
||||
sodium.crypto_hash_sha256_update(state, input.asByteArray(), input.size.toLong())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) {
|
||||
println("Debug")
|
||||
sodium.crypto_hash_sha256_final(state, out.asByteArray())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_init(state: Sha512State): Int {
|
||||
println("Debug")
|
||||
return sodium.crypto_hash_sha512_init(state)
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) {
|
||||
println("Debug")
|
||||
sodium.crypto_hash_sha512_update(state, input.asByteArray(), input.size.toLong())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) {
|
||||
println("Debug")
|
||||
sodium.crypto_hash_sha512_final(state, out.asByteArray())
|
||||
}
|
||||
|
||||
actual fun crypto_generichash_init(
|
||||
state: UByteArray,
|
||||
state: GenericHashState,
|
||||
key: UByteArray,
|
||||
outlen: Int
|
||||
): Int {
|
||||
println("Debug")
|
||||
return sodium.crypto_generichash_init(state.asByteArray(), key.asByteArray(), key.size, outlen)
|
||||
return sodium.crypto_generichash_init(state, key.asByteArray(), key.size, outlen)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package debug.test
|
||||
|
||||
import kotlin.Int
|
||||
import kotlin.UByteArray
|
||||
import kotlinx.cinterop.convert
|
||||
import kotlinx.cinterop.ptr
|
||||
import kotlinx.cinterop.toCValues
|
||||
import libsodium.crypto_generichash_blake2b_state
|
||||
import libsodium.crypto_hash_sha256_state
|
||||
import libsodium.crypto_hash_sha512_state
|
||||
|
||||
actual typealias Sha256State = crypto_hash_sha256_state
|
||||
|
||||
actual typealias Sha512State = crypto_hash_sha512_state
|
||||
|
||||
actual typealias GenericHashState = crypto_generichash_blake2b_state
|
||||
|
||||
actual class Crypto {
|
||||
actual fun crypto_hash_sha256_init(state: Sha256State): Int {
|
||||
println("Debug")
|
||||
return libsodium.crypto_hash_sha256_init(state.ptr)
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) {
|
||||
println("Debug")
|
||||
libsodium.crypto_hash_sha256_update(state.ptr, input.toCValues(), input.size.convert())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) {
|
||||
println("Debug")
|
||||
libsodium.crypto_hash_sha256_final(state.ptr, out.toCValues())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_init(state: Sha512State): Int {
|
||||
println("Debug")
|
||||
return libsodium.crypto_hash_sha512_init(state.ptr)
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) {
|
||||
println("Debug")
|
||||
libsodium.crypto_hash_sha512_update(state.ptr, input.toCValues(), input.size.convert())
|
||||
}
|
||||
|
||||
actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) {
|
||||
println("Debug")
|
||||
libsodium.crypto_hash_sha512_final(state.ptr, out.toCValues())
|
||||
}
|
||||
|
||||
actual fun crypto_generichash_init(
|
||||
state: GenericHashState,
|
||||
key: UByteArray,
|
||||
outlen: Int
|
||||
): Int {
|
||||
println("Debug")
|
||||
return libsodium.crypto_generichash_init(state.ptr, key.toCValues(), key.size.convert(),
|
||||
outlen.convert())
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package debug.test
|
||||
|
||||
import libsodium.crypto_hash_sha256_state
|
||||
|
||||
actual typealias Sha256State = crypto_hash_sha256_state
|
Loading…
x
Reference in New Issue
Block a user