Pivot to a handled API, update common js and native generators

This commit is contained in:
Ugljesa Jovanovic 2020-08-08 16:20:56 +02:00 committed by Ugljesa Jovanovic
parent d8b92a6970
commit 1f0eaf59ca
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
12 changed files with 419 additions and 258 deletions

View File

@ -35,6 +35,10 @@ class ClassDefinition(
operator fun FunctionDefinition.unaryPlus() { operator fun FunctionDefinition.unaryPlus() {
methods.add(this) methods.add(this)
} }
operator fun List<FunctionDefinition>.unaryPlus() {
methods.addAll(this)
}
} }
class InnerClassDefinition( class InnerClassDefinition(
@ -51,7 +55,10 @@ class FunctionDefinition(
val jsName: String, val jsName: String,
val nativeName: String, val nativeName: String,
val parameterList: MutableList<ParameterDefinition> = mutableListOf(), val parameterList: MutableList<ParameterDefinition> = mutableListOf(),
val returnType: GeneralTypeDefinition val returnType: GeneralTypeDefinition,
val dynamicJsReturn: Boolean = false,
val isStateCreationFunction: Boolean = false,
val outputLengthWhenArray: Int = -1
) { ) {
operator fun ParameterDefinition.unaryPlus() { operator fun ParameterDefinition.unaryPlus() {
parameterList.add(this) parameterList.add(this)
@ -61,7 +68,10 @@ class FunctionDefinition(
class ParameterDefinition( class ParameterDefinition(
val parameterName: String, val parameterName: String,
val parameterType: GeneralTypeDefinition, val parameterType: GeneralTypeDefinition,
val modifiesReturn: Boolean = false val modifiesReturn: Boolean = false,
val isActuallyAnOutputParam: Boolean = false,
val isStateType: Boolean = false,
val dropParameterFromDefinition: Boolean = false,
) )
interface GeneralTypeDefinition { interface GeneralTypeDefinition {
@ -116,9 +126,21 @@ fun funcDef(
jsName: String, jsName: String,
nativeName: String, nativeName: String,
returnType: GeneralTypeDefinition, returnType: GeneralTypeDefinition,
dynamicJsReturn: Boolean = false,
isStateCreationFunction: Boolean = false,
outputLengthWhenArray: Int = -1,
body: FunctionDefinition.() -> Unit body: FunctionDefinition.() -> Unit
): FunctionDefinition { ): FunctionDefinition {
val function = FunctionDefinition(name, javaName, jsName, nativeName, returnType = returnType) val function = FunctionDefinition(
name,
javaName,
jsName,
nativeName,
returnType = returnType,
dynamicJsReturn = dynamicJsReturn,
isStateCreationFunction = isStateCreationFunction,
outputLengthWhenArray = outputLengthWhenArray
)
function.body() function.body()
return function return function
} }
@ -126,9 +148,22 @@ fun funcDef(
fun funcDef( fun funcDef(
name: String, name: String,
returnType: GeneralTypeDefinition, returnType: GeneralTypeDefinition,
dynamicJsReturn: Boolean = false,
isStateCreationFunction: Boolean = false,
outputLengthWhenArray: Int = -1,
body: FunctionDefinition.() -> Unit body: FunctionDefinition.() -> Unit
): FunctionDefinition { ): FunctionDefinition {
val function = FunctionDefinition(name, name, name, name, returnType = returnType) val function =
FunctionDefinition(
name,
name,
name,
name,
returnType = returnType,
dynamicJsReturn = dynamicJsReturn,
isStateCreationFunction = isStateCreationFunction,
outputLengthWhenArray = outputLengthWhenArray
)
function.body() function.body()
return function return function
} }

View File

@ -8,82 +8,8 @@ package com.ionspin.kotlin.crypto.generator.libsodium.definitions
object LibSodiumDefinitions { object LibSodiumDefinitions {
val testKotlinFile = fileDef("DebugTest") { val testKotlinFile = fileDef("DebugTest") {
+classDef("Crypto") { +classDef("Crypto") {
defineHashFunctions()
/* defineGenericHashFunctions()
--------------- 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)
}
}
} }
} }

View File

@ -0,0 +1,37 @@
package com.ionspin.kotlin.crypto.generator.libsodium.definitions
import com.squareup.kotlinpoet.ClassName
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 04-Aug-2020
*/
fun ClassDefinition.defineGenericHashFunctions() {
/*
* ------------- GENERIC HASH (BLAKE2B)
*/
+innerClassDef(
"GenericHashState",
"ByteArray",
"Uint8Array",
"crypto_generichash_blake2b_state"
)
+funcDef(
"crypto_generichash_init",
CustomTypeDefinition(ClassName(packageName, "GenericHashState")),
true,
isStateCreationFunction = true
) {
+ParameterDefinition(
"state",
CustomTypeDefinition((withPackageName("GenericHashState"))),
isStateType = true,
dropParameterFromDefinition = true
)
+ParameterDefinition("key", TypeDefinition.ARRAY_OF_UBYTES)
+ParameterDefinition("outlen", TypeDefinition.INT, modifiesReturn = true)
}
}

View File

@ -0,0 +1,80 @@
package com.ionspin.kotlin.crypto.generator.libsodium.definitions
import com.squareup.kotlinpoet.ClassName
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 04-Aug-2020
*/
fun ClassDefinition.defineHashFunctions() {
/*
--------------- SHA256
*/
+innerClassDef(
"Sha256State",
"com.goterl.lazycode.lazysodium.interfaces.Hash.State256",
"Sha256State",
"crypto_hash_sha256_state"
)
+funcDef(
"crypto_hash_sha256_init",
CustomTypeDefinition(ClassName(packageName, "Sha256State")),
dynamicJsReturn = true,
isStateCreationFunction = true
) {
+ParameterDefinition(
"state",
CustomTypeDefinition((withPackageName("Sha256State"))),
dropParameterFromDefinition = true,
isStateType = true
)
}
+funcDef("crypto_hash_sha256_update", TypeDefinition.UNIT) {
+ParameterDefinition(
"state",
CustomTypeDefinition((withPackageName("Sha256State"))),
isStateType = true
)
+ParameterDefinition("input", TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE)
}
+funcDef("crypto_hash_sha256_final", TypeDefinition.ARRAY_OF_UBYTES, outputLengthWhenArray = 32) {
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha256State"))))
+ParameterDefinition("out", TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, isActuallyAnOutputParam = true, dropParameterFromDefinition = true)
}
/*
--------------- SHA512
*/
+innerClassDef(
"Sha512State",
"com.goterl.lazycode.lazysodium.interfaces.Hash.State512",
"Sha512State",
"crypto_hash_sha512_state"
)
+funcDef(
"crypto_hash_sha512_init",
CustomTypeDefinition(ClassName(packageName, "Sha512State")),
true,
isStateCreationFunction = true
) {
+ParameterDefinition(
"state",
CustomTypeDefinition((withPackageName("Sha512State"))),
dropParameterFromDefinition = true,
isStateType = true
)
}
+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.ARRAY_OF_UBYTES, outputLengthWhenArray = 64) {
+ParameterDefinition("state", CustomTypeDefinition((withPackageName("Sha512State"))))
+ParameterDefinition("out", TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, isActuallyAnOutputParam = true, dropParameterFromDefinition = true)
}
}

View File

@ -51,12 +51,24 @@ object CommonLibsodiumGenerator {
fun createCommonMethodSpec(methodDefinition: FunctionDefinition): FunSpec { fun createCommonMethodSpec(methodDefinition: FunctionDefinition): FunSpec {
val methodBuilder = FunSpec.builder(methodDefinition.name) val methodBuilder = FunSpec.builder(methodDefinition.name)
var actualReturnType : TypeName = Any::class.asTypeName()
var actualReturnTypeFound : Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.dropParameterFromDefinition.not()) {
val parameterSpec = val parameterSpec =
ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName) ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName)
methodBuilder.addParameter(parameterSpec.build()) methodBuilder.addParameter(parameterSpec.build())
} }
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnTypeFound = true
actualReturnType = paramDefinition.parameterType.typeName
}
}
if (actualReturnTypeFound) {
methodBuilder.returns(actualReturnType)
} else {
methodBuilder.returns(methodDefinition.returnType.typeName) methodBuilder.returns(methodDefinition.returnType.typeName)
}
return methodBuilder.build() return methodBuilder.build()
} }

View File

@ -14,6 +14,7 @@ object JsLibsodiumGenerator {
fun createJsFile(packageName: String, fileDefinition: KotlinFileDefinition): FileSpec { fun createJsFile(packageName: String, fileDefinition: KotlinFileDefinition): FileSpec {
val fileBuilder = FileSpec.builder(packageName, fileDefinition.name) val fileBuilder = FileSpec.builder(packageName, fileDefinition.name)
fileBuilder.addImport("ext.libsodium.com.ionspin.kotlin.crypto", "toUInt8Array") fileBuilder.addImport("ext.libsodium.com.ionspin.kotlin.crypto", "toUInt8Array")
fileBuilder.addImport("ext.libsodium.com.ionspin.kotlin.crypto", "toUByteArray")
fileBuilder.addImport("com.ionspin.kotlin.crypto", "getSodium") fileBuilder.addImport("com.ionspin.kotlin.crypto", "getSodium")
for (commonClassDefinition in fileDefinition.commonClassList) { for (commonClassDefinition in fileDefinition.commonClassList) {
//Create type-aliases //Create type-aliases
@ -48,10 +49,14 @@ object JsLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false var returnModifierFound = false
var returnModifierName = "" var returnModifierName = ""
var actualReturnType: TypeName = DYNAMIC
var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.isActuallyAnOutputParam.not()) {
val parameterSpec = val parameterSpec =
ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName) ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName)
methodBuilder.addParameter(parameterSpec.build()) methodBuilder.addParameter(parameterSpec.build())
}
if (paramDefinition.modifiesReturn) { if (paramDefinition.modifiesReturn) {
if (returnModifierFound == true) { if (returnModifierFound == true) {
throw RuntimeException("Return modifier already found") throw RuntimeException("Return modifier already found")
@ -59,53 +64,51 @@ object JsLibsodiumGenerator {
returnModifierFound = true returnModifierFound = true
returnModifierName = paramDefinition.parameterName returnModifierName = paramDefinition.parameterName
} }
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnTypeFound = true
actualReturnType = paramDefinition.parameterType.typeName
}
} }
if (methodDefinition.returnType == TypeDefinition.ARRAY_OF_UBYTES) {
methodBuilder.addStatement("println(\"Debug\")") methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder() val constructJsCall = StringBuilder()
constructJvmCall.append("return getSodium().${methodDefinition.javaName}") when (methodDefinition.returnType) {
constructJvmCall.append(paramsToString(methodDefinition)) TypeDefinition.ARRAY_OF_UBYTES -> {
constructJsCall.append("return getSodium().${methodDefinition.javaName}")
methodBuilder.addStatement(constructJvmCall.toString()) constructJsCall.append(paramsToString(methodDefinition) + ".toUByteArray()")
} }
TypeDefinition.INT -> {
if (methodDefinition.returnType == TypeDefinition.INT) { constructJsCall.append("return getSodium().${methodDefinition.javaName}")
methodBuilder.addStatement("println(\"Debug\")") constructJsCall.append(paramsToString(methodDefinition))
val constructJvmCall = StringBuilder() }
constructJvmCall.append("return getSodium().${methodDefinition.javaName}") TypeDefinition.UNIT -> {
constructJvmCall.append(paramsToString(methodDefinition)) constructJsCall.append("getSodium().${methodDefinition.javaName}")
constructJsCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString()) }
} is CustomTypeDefinition -> {
constructJsCall.append("return getSodium().${methodDefinition.javaName}")
if (methodDefinition.returnType == TypeDefinition.UNIT) { constructJsCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement("println(\"Debug\")") }
val constructJvmCall = StringBuilder() }
constructJvmCall.append("getSodium().${methodDefinition.javaName}") methodBuilder.addStatement(constructJsCall.toString())
constructJvmCall.append(paramsToString(methodDefinition)) if (actualReturnTypeFound) {
methodBuilder.returns(actualReturnType)
methodBuilder.addStatement(constructJvmCall.toString()) return methodBuilder.build()
}
if (methodDefinition.returnType is CustomTypeDefinition) {
methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder()
constructJvmCall.append("return getSodium().${methodDefinition.javaName}")
constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
} }
if (methodDefinition.dynamicJsReturn) {
methodBuilder.returns(Dynamic)
} else {
methodBuilder.returns(methodDefinition.returnType.typeName) methodBuilder.returns(methodDefinition.returnType.typeName)
}
return methodBuilder.build() return methodBuilder.build()
} }
fun paramsToString(methodDefinition: FunctionDefinition): String { fun paramsToString(methodDefinition: FunctionDefinition): String {
val paramsBuilder = StringBuilder() val paramsBuilder = StringBuilder()
paramsBuilder.append("(") paramsBuilder.append("(")
methodDefinition.parameterList.forEachIndexed { index, paramDefinition -> val jsParams = methodDefinition.parameterList.filter { it.dropParameterFromDefinition.not() }
val separator = if (index == methodDefinition.parameterList.size - 1) { jsParams.forEachIndexed { index, paramDefinition ->
val separator = if (index == jsParams.size - 1) {
"" ""
} else { } else {
", " ", "
@ -116,10 +119,10 @@ object JsLibsodiumGenerator {
if (paramDefinition.parameterType is TypeDefinition) { if (paramDefinition.parameterType is TypeDefinition) {
when (paramDefinition.parameterType) { when (paramDefinition.parameterType) {
TypeDefinition.ARRAY_OF_UBYTES -> { TypeDefinition.ARRAY_OF_UBYTES -> {
paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array(), " + paramDefinition.parameterName + ".size" + separator) paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array()" + separator)
} }
TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> { TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array(), " + paramDefinition.parameterName + ".size.toLong()" + separator) paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array(), " + separator)
} }
TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE -> { TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE -> {
paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array()" + separator) paramsBuilder.append(paramDefinition.parameterName + ".toUInt8Array()" + separator)
@ -136,11 +139,11 @@ object JsLibsodiumGenerator {
} }
} }
} }
paramsBuilder.append(')') paramsBuilder.append(')')
return paramsBuilder.toString() return paramsBuilder.toString()
} }
} }

View File

@ -62,42 +62,27 @@ object JvmLibsodiumGenerator {
} }
} }
if (methodDefinition.returnType == TypeDefinition.ARRAY_OF_UBYTES) {
methodBuilder.addStatement("println(\"Debug\")") methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder() val constructJvmCall = StringBuilder()
constructJvmCall.append("return sodium.${methodDefinition.javaName}") when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> {
constructJvmCall.append("return sodium.${methodDefinition.nativeName}")
constructJvmCall.append(paramsToString(methodDefinition)) constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
} }
TypeDefinition.INT -> {
if (methodDefinition.returnType == TypeDefinition.INT) { constructJvmCall.append("return sodium.${methodDefinition.nativeName}")
methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder()
constructJvmCall.append("return sodium.${methodDefinition.javaName}")
constructJvmCall.append(paramsToString(methodDefinition)) constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
} }
TypeDefinition.UNIT -> {
if (methodDefinition.returnType == TypeDefinition.UNIT) { constructJvmCall.append("sodium.${methodDefinition.nativeName}")
methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder()
constructJvmCall.append("sodium.${methodDefinition.javaName}")
constructJvmCall.append(paramsToString(methodDefinition)) constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
} }
is CustomTypeDefinition -> {
if (methodDefinition.returnType is CustomTypeDefinition) { constructJvmCall.append("return sodium.${methodDefinition.nativeName}")
methodBuilder.addStatement("println(\"Debug\")")
val constructJvmCall = StringBuilder()
constructJvmCall.append("return sodium.${methodDefinition.javaName}")
constructJvmCall.append(paramsToString(methodDefinition)) constructJvmCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructJvmCall.toString())
} }
}
methodBuilder.addStatement(constructJvmCall.toString())
methodBuilder.returns(methodDefinition.returnType.typeName) methodBuilder.returns(methodDefinition.returnType.typeName)
return methodBuilder.build() return methodBuilder.build()
} }

View File

@ -1,7 +1,19 @@
package com.ionspin.kotlin.crypto.generator.libsodium.generator package com.ionspin.kotlin.crypto.generator.libsodium.generator
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.* import com.ionspin.kotlin.crypto.generator.libsodium.definitions.CustomTypeDefinition
import com.squareup.kotlinpoet.* import com.ionspin.kotlin.crypto.generator.libsodium.definitions.FunctionDefinition
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.InnerClassDefinition
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.KotlinFileDefinition
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.ParameterDefinition
import com.ionspin.kotlin.crypto.generator.libsodium.definitions.TypeDefinition
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeAliasSpec
import com.squareup.kotlinpoet.asTypeName
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic
@ -18,6 +30,9 @@ object NativeLibsodiumGenerator {
fileBuilder.addImport("kotlinx.cinterop", "ptr") fileBuilder.addImport("kotlinx.cinterop", "ptr")
fileBuilder.addImport("kotlinx.cinterop", "pin") fileBuilder.addImport("kotlinx.cinterop", "pin")
fileBuilder.addImport("kotlinx.cinterop", "addressOf") fileBuilder.addImport("kotlinx.cinterop", "addressOf")
fileBuilder.addImport("kotlinx.cinterop", "reinterpret")
fileBuilder.addImport("kotlinx.cinterop", "pointed")
fileBuilder.addImport("libsodium", "sodium_malloc")
for (commonClassDefinition in fileDefinition.commonClassList) { for (commonClassDefinition in fileDefinition.commonClassList) {
//Create type-aliases //Create type-aliases
@ -33,7 +48,7 @@ object NativeLibsodiumGenerator {
//Workarounds for native not emitting types //Workarounds for native not emitting types
val byteEmitter = PropertySpec.builder("_emitByte", Byte::class.asTypeName()) val byteEmitter = PropertySpec.builder("_emitByte", Byte::class.asTypeName())
byteEmitter.initializer(CodeBlock.of("0")) byteEmitter.initializer(CodeBlock.of("0"))
val byteArrayEmitter = PropertySpec.builder("_emitByteArray", Byte::class.asTypeName()) val byteArrayEmitter = PropertySpec.builder("_emitByteArray", ByteArray::class.asTypeName())
byteArrayEmitter.initializer(CodeBlock.of("ByteArray(0) {}")) byteArrayEmitter.initializer(CodeBlock.of("ByteArray(0) {}"))
commonClassSpec.addProperty(byteEmitter.build()) commonClassSpec.addProperty(byteEmitter.build())
commonClassSpec.addProperty(byteArrayEmitter.build()) commonClassSpec.addProperty(byteArrayEmitter.build())
@ -60,10 +75,17 @@ object NativeLibsodiumGenerator {
methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList methodBuilder.modifiers += MultiplatformModifier.ACTUAL.modifierList
var returnModifierFound = false var returnModifierFound = false
var returnModifierName = "" var returnModifierName = ""
lateinit var actualReturnParameterDefinition: ParameterDefinition
var actualReturnTypeFound: Boolean = false
for (paramDefinition in methodDefinition.parameterList) { for (paramDefinition in methodDefinition.parameterList) {
if (paramDefinition.isStateType && methodDefinition.isStateCreationFunction) {
createStateParam(paramDefinition, methodBuilder)
}
if ((paramDefinition.isStateType.not() || methodDefinition.isStateCreationFunction.not()) && paramDefinition.isActuallyAnOutputParam.not()) {
val parameterSpec = val parameterSpec =
ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName) ParameterSpec.builder(paramDefinition.parameterName, paramDefinition.parameterType.typeName)
methodBuilder.addParameter(parameterSpec.build()) methodBuilder.addParameter(parameterSpec.build())
}
if (paramDefinition.modifiesReturn) { if (paramDefinition.modifiesReturn) {
if (returnModifierFound == true) { if (returnModifierFound == true) {
throw RuntimeException("Return modifier already found") throw RuntimeException("Return modifier already found")
@ -71,52 +93,103 @@ object NativeLibsodiumGenerator {
returnModifierFound = true returnModifierFound = true
returnModifierName = paramDefinition.parameterName returnModifierName = paramDefinition.parameterName
} }
if (paramDefinition.isActuallyAnOutputParam) {
actualReturnParameterDefinition = paramDefinition
actualReturnTypeFound = true
}
}
if (actualReturnTypeFound) {
if (returnModifierFound) {
createOutputParam(actualReturnParameterDefinition, returnModifierName, methodBuilder)
} else {
if (methodDefinition.outputLengthWhenArray == -1) {
throw RuntimeException("Function definition lacks a way to define output array length, function ${methodDefinition.name}")
}
createOutputParam(actualReturnParameterDefinition, methodDefinition.outputLengthWhenArray.toString(), methodBuilder)
}
} }
pinParams(methodDefinition, methodBuilder) pinParams(methodDefinition, methodBuilder)
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) {
val constructNativeCall = StringBuilder() val constructNativeCall = StringBuilder()
if (methodDefinition.isStateCreationFunction) {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}") constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition)) constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString()) methodBuilder.addStatement(constructNativeCall.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())
}
unpinParams(methodDefinition, methodBuilder) unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return state")
} else if (actualReturnTypeFound) {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return out")
} else {
when (methodDefinition.returnType) {
TypeDefinition.ARRAY_OF_UBYTES -> {
constructNativeCall.append("val result = libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return result")
}
TypeDefinition.INT -> {
constructNativeCall.append("val result = libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return result")
}
TypeDefinition.UNIT -> {
constructNativeCall.append("libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
}
is CustomTypeDefinition -> {
constructNativeCall.append("val result = libsodium.${methodDefinition.nativeName}")
constructNativeCall.append(paramsToString(methodDefinition))
methodBuilder.addStatement(constructNativeCall.toString())
unpinParams(methodDefinition, methodBuilder)
methodBuilder.addStatement("return result")
}
}
}
methodBuilder.returns(methodDefinition.returnType.typeName) methodBuilder.returns(methodDefinition.returnType.typeName)
return methodBuilder.build() return methodBuilder.build()
} }
fun createStateParam(stateParameterDefinition: ParameterDefinition, methodBuilder: FunSpec.Builder) {
/*
val allocated = sodium_malloc(crypto_hash_sha256_state.size.convert())!!
state = allocated.reinterpret<crypto_hash_sha256_state>().pointed
*/
methodBuilder.addStatement("val allocated = sodium_malloc(${stateParameterDefinition.parameterType.typeName}.size.convert())!!")
methodBuilder.addStatement("val state = allocated.reinterpret<${stateParameterDefinition.parameterType.typeName}>().pointed")
}
fun createOutputParam(outputParam: ParameterDefinition, length: String?, methodBuilder: FunSpec.Builder) {
/*
val hashResult = UByteArray(Sha256Properties.MAX_HASH_BYTES)
val hashResultPinned = hashResult.pin()
crypto_hash_sha256_final(state.ptr, hashResultPinned.addressOf(0))
sodium_free(state.ptr)
return hashResult
*/
when (outputParam.parameterType) {
TypeDefinition.ARRAY_OF_UBYTES, TypeDefinition.ARRAY_OF_UBYTES_NO_SIZE, TypeDefinition.ARRAY_OF_UBYTES_LONG_SIZE -> {
methodBuilder.addStatement("val out = UByteArray($length)")
}
else -> {
throw RuntimeException("Unhandled native output param type: ${outputParam.parameterType.typeName}")
}
}
}
fun pinParams(methodDefinition: FunctionDefinition, methodBuilder: FunSpec.Builder) { fun pinParams(methodDefinition: FunctionDefinition, methodBuilder: FunSpec.Builder) {
methodDefinition.parameterList.forEachIndexed { index, paramDefinition -> methodDefinition.parameterList.forEachIndexed { index, paramDefinition ->
if (paramDefinition.parameterType is TypeDefinition) { if (paramDefinition.parameterType is TypeDefinition) {

View File

@ -10,21 +10,17 @@ expect class Sha512State
expect class GenericHashState expect class GenericHashState
expect class Crypto { expect class Crypto {
fun crypto_hash_sha256_init(state: Sha256State): Int fun crypto_hash_sha256_init(): Sha256State
fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray)
fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) fun crypto_hash_sha256_final(state: Sha256State): UByteArray
fun crypto_hash_sha512_init(state: Sha512State): Int fun crypto_hash_sha512_init(): Sha512State
fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray)
fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) fun crypto_hash_sha512_final(state: Sha512State): UByteArray
fun crypto_generichash_init( fun crypto_generichash_init(key: UByteArray, outlen: Int): GenericHashState
state: GenericHashState,
key: UByteArray,
outlen: Int
): Int
} }

View File

@ -1,6 +1,7 @@
package debug.test package debug.test
import com.ionspin.kotlin.crypto.getSodium import com.ionspin.kotlin.crypto.getSodium
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
import kotlin.Any import kotlin.Any
import kotlin.Int import kotlin.Int
@ -13,42 +14,38 @@ actual typealias Sha512State = Any
actual typealias GenericHashState = Any actual typealias GenericHashState = Any
actual class Crypto { actual class Crypto {
actual fun crypto_hash_sha256_init(state: Sha256State): Int { actual fun crypto_hash_sha256_init(): dynamic {
println("Debug") println("Debug")
return getSodium().crypto_hash_sha256_init(state) return getSodium().crypto_hash_sha256_init()
} }
actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) { actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) {
println("Debug") println("Debug")
getSodium().crypto_hash_sha256_update(state, input.toUInt8Array(), input.size.toLong()) getSodium().crypto_hash_sha256_update(state, input.toUInt8Array(), )
} }
actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) { actual fun crypto_hash_sha256_final(state: Sha256State): UByteArray {
println("Debug") println("Debug")
getSodium().crypto_hash_sha256_final(state, out.toUInt8Array()) return getSodium().crypto_hash_sha256_final(state).toUByteArray()
} }
actual fun crypto_hash_sha512_init(state: Sha512State): Int { actual fun crypto_hash_sha512_init(): dynamic {
println("Debug") println("Debug")
return getSodium().crypto_hash_sha512_init(state) return getSodium().crypto_hash_sha512_init()
} }
actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) { actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) {
println("Debug") println("Debug")
getSodium().crypto_hash_sha512_update(state, input.toUInt8Array(), input.size.toLong()) getSodium().crypto_hash_sha512_update(state, input.toUInt8Array(), )
} }
actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) { actual fun crypto_hash_sha512_final(state: Sha512State): UByteArray {
println("Debug") println("Debug")
getSodium().crypto_hash_sha512_final(state, out.toUInt8Array()) return getSodium().crypto_hash_sha512_final(state).toUByteArray()
} }
actual fun crypto_generichash_init( actual fun crypto_generichash_init(key: UByteArray, outlen: Int): dynamic {
state: GenericHashState,
key: UByteArray,
outlen: Int
): Int {
println("Debug") println("Debug")
return getSodium().crypto_generichash_init(state, key.toUInt8Array(), key.size, outlen) return getSodium().crypto_generichash_init(key.toUInt8Array(), outlen)
} }
} }

View File

@ -15,7 +15,7 @@ actual typealias Sha512State = Hash.State512
actual typealias GenericHashState = ByteArray actual typealias GenericHashState = ByteArray
actual class Crypto { actual class Crypto {
actual fun crypto_hash_sha256_init(state: Sha256State): Int { actual fun crypto_hash_sha256_init(state: Sha256State): Sha256State {
println("Debug") println("Debug")
return sodium.crypto_hash_sha256_init(state) return sodium.crypto_hash_sha256_init(state)
} }
@ -25,12 +25,12 @@ actual class Crypto {
sodium.crypto_hash_sha256_update(state, input.asByteArray(), input.size.toLong()) sodium.crypto_hash_sha256_update(state, input.asByteArray(), input.size.toLong())
} }
actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) { actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray): UByteArray {
println("Debug") println("Debug")
sodium.crypto_hash_sha256_final(state, out.asByteArray()) return sodium.crypto_hash_sha256_final(state, out.asByteArray())
} }
actual fun crypto_hash_sha512_init(state: Sha512State): Int { actual fun crypto_hash_sha512_init(state: Sha512State): Sha512State {
println("Debug") println("Debug")
return sodium.crypto_hash_sha512_init(state) return sodium.crypto_hash_sha512_init(state)
} }
@ -40,16 +40,16 @@ actual class Crypto {
sodium.crypto_hash_sha512_update(state, input.asByteArray(), input.size.toLong()) sodium.crypto_hash_sha512_update(state, input.asByteArray(), input.size.toLong())
} }
actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) { actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray): UByteArray {
println("Debug") println("Debug")
sodium.crypto_hash_sha512_final(state, out.asByteArray()) return sodium.crypto_hash_sha512_final(state, out.asByteArray())
} }
actual fun crypto_generichash_init( actual fun crypto_generichash_init(
state: GenericHashState, state: GenericHashState,
key: UByteArray, key: UByteArray,
outlen: Int outlen: Int
): Int { ): GenericHashState {
println("Debug") println("Debug")
return sodium.crypto_generichash_init(state, key.asByteArray(), key.size, outlen) return sodium.crypto_generichash_init(state, key.asByteArray(), key.size, outlen)
} }

View File

@ -1,16 +1,20 @@
package debug.test package debug.test
import kotlin.Byte import kotlin.Byte
import kotlin.ByteArray
import kotlin.Int import kotlin.Int
import kotlin.UByteArray import kotlin.UByteArray
import kotlinx.cinterop.addressOf import kotlinx.cinterop.addressOf
import kotlinx.cinterop.convert import kotlinx.cinterop.convert
import kotlinx.cinterop.pin import kotlinx.cinterop.pin
import kotlinx.cinterop.pointed
import kotlinx.cinterop.ptr import kotlinx.cinterop.ptr
import kotlinx.cinterop.reinterpret
import kotlinx.cinterop.toCValues import kotlinx.cinterop.toCValues
import libsodium.crypto_generichash_blake2b_state import libsodium.crypto_generichash_blake2b_state
import libsodium.crypto_hash_sha256_state import libsodium.crypto_hash_sha256_state
import libsodium.crypto_hash_sha512_state import libsodium.crypto_hash_sha512_state
import libsodium.sodium_malloc
actual typealias Sha256State = crypto_hash_sha256_state actual typealias Sha256State = crypto_hash_sha256_state
@ -21,51 +25,64 @@ actual typealias GenericHashState = crypto_generichash_blake2b_state
actual class Crypto { actual class Crypto {
val _emitByte: Byte = 0 val _emitByte: Byte = 0
val _emitByteArray: Byte = ByteArray(0) {} val _emitByteArray: ByteArray = ByteArray(0) {}
actual fun crypto_hash_sha256_init(state: Sha256State): Int { actual fun crypto_hash_sha256_init(): Sha256State {
val allocated = sodium_malloc(debug.test.Sha256State.size.convert())!!
val state = allocated.reinterpret<debug.test.Sha256State>().pointed
println("Debug") println("Debug")
return libsodium.crypto_hash_sha256_init(state.ptr) libsodium.crypto_hash_sha256_init(state.ptr)
return state
} }
actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) { actual fun crypto_hash_sha256_update(state: Sha256State, input: UByteArray) {
println("Debug")
val pinnedInput = input.pin() val pinnedInput = input.pin()
libsodium.crypto_hash_sha256_update(state.ptr, pinnedInput.addressOf(0), input.size.convert()) libsodium.crypto_hash_sha256_update(state.ptr, pinnedInput.addressOf(0), input.size.convert())
pinnedInput.unpin() pinnedInput.unpin()
} }
actual fun crypto_hash_sha256_final(state: Sha256State, out: UByteArray) { actual fun crypto_hash_sha256_final(state: Sha256State): UByteArray {
println("Debug")
val out = UByteArray(32)
val pinnedOut = out.pin() val pinnedOut = out.pin()
libsodium.crypto_hash_sha256_final(state.ptr, pinnedOut.addressOf(0)) libsodium.crypto_hash_sha256_final(state.ptr, pinnedOut.addressOf(0))
pinnedOut.unpin() pinnedOut.unpin()
return out
} }
actual fun crypto_hash_sha512_init(state: Sha512State): Int { actual fun crypto_hash_sha512_init(): Sha512State {
val allocated = sodium_malloc(debug.test.Sha512State.size.convert())!!
val state = allocated.reinterpret<debug.test.Sha512State>().pointed
println("Debug") println("Debug")
return libsodium.crypto_hash_sha512_init(state.ptr) libsodium.crypto_hash_sha512_init(state.ptr)
return state
} }
actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) { actual fun crypto_hash_sha512_update(state: Sha512State, input: UByteArray) {
println("Debug")
val pinnedInput = input.pin() val pinnedInput = input.pin()
libsodium.crypto_hash_sha512_update(state.ptr, pinnedInput.addressOf(0), input.size.convert()) libsodium.crypto_hash_sha512_update(state.ptr, pinnedInput.addressOf(0), input.size.convert())
pinnedInput.unpin() pinnedInput.unpin()
} }
actual fun crypto_hash_sha512_final(state: Sha512State, out: UByteArray) { actual fun crypto_hash_sha512_final(state: Sha512State): UByteArray {
println("Debug")
val out = UByteArray(64)
val pinnedOut = out.pin() val pinnedOut = out.pin()
libsodium.crypto_hash_sha512_final(state.ptr, pinnedOut.addressOf(0)) libsodium.crypto_hash_sha512_final(state.ptr, pinnedOut.addressOf(0))
pinnedOut.unpin() pinnedOut.unpin()
return out
} }
actual fun crypto_generichash_init( actual fun crypto_generichash_init(key: UByteArray, outlen: Int): GenericHashState {
state: GenericHashState, val allocated = sodium_malloc(debug.test.GenericHashState.size.convert())!!
key: UByteArray, val state = allocated.reinterpret<debug.test.GenericHashState>().pointed
outlen: Int
): Int {
val pinnedKey = key.pin()
println("Debug") println("Debug")
return libsodium.crypto_generichash_init(state.ptr, pinnedKey.addressOf(0), key.size.convert(), val pinnedKey = key.pin()
libsodium.crypto_generichash_init(state.ptr, pinnedKey.addressOf(0), key.size.convert(),
outlen.convert()) outlen.convert())
pinnedKey.unpin() pinnedKey.unpin()
return state
} }
} }