From 1aaffe9c7cd9cd8049902f9056ad4b2e82c83fc6 Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Sun, 2 Aug 2020 17:09:13 +0200 Subject: [PATCH] Starting work on JS generator --- .../generator/JsLibsodiumGenerator.kt | 147 ++++++++++++++++++ .../generator/NativeLibsodiumGenerator.kt | 4 +- .../com/ionspin/kotlin/crypto/JsUtil.kt | 2 - .../com/ionspin/kotlin/crypto/JsUtil.kt | 24 +++ 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt new file mode 100644 index 0000000..3eb9312 --- /dev/null +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/JsLibsodiumGenerator.kt @@ -0,0 +1,147 @@ +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 JsLibsodiumGenerator { + + + fun createJsFile(packageName: String, fileDefinition: KotlinFileDefinition): FileSpec { + val fileBuilder = FileSpec.builder(packageName, fileDefinition.name) + 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(createJsInnerClassSpec(it, MultiplatformModifier.ACTUAL)) + } + + val commonClassSpec = createClass( + commonClassDefinition, + MultiplatformModifier.ACTUAL, + ::createJsFunctionImplementation + ) + fileBuilder.addType(commonClassSpec) + } + val file = fileBuilder.build() + file.writeTo(System.out) + return file + } + + fun createJsInnerClassSpec( + innerClassDefinition: InnerClassDefinition, + multiplatformModifier: MultiplatformModifier + ): TypeAliasSpec { + val innerClassBuilder = TypeAliasSpec.builder(innerClassDefinition.name, ClassName.bestGuess(innerClassDefinition.javaName)) + innerClassBuilder.modifiers += multiplatformModifier.modifierList + + return innerClassBuilder.build() + } + + fun createJsFunctionImplementation(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 sodium.${methodDefinition.javaName}") + constructJvmCall.append(paramsToString(methodDefinition)) + + methodBuilder.addStatement(constructJvmCall.toString()) + } + + if (methodDefinition.returnType == TypeDefinition.INT) { + methodBuilder.addStatement("println(\"Debug\")") + val constructJvmCall = StringBuilder() + constructJvmCall.append("return sodium.${methodDefinition.javaName}") + constructJvmCall.append(paramsToString(methodDefinition)) + + 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() + constructJvmCall.append("return sodium.${methodDefinition.javaName}") + 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 + separator) + } + if (paramDefinition.parameterType is TypeDefinition) { + when(paramDefinition.parameterType) { + TypeDefinition.ARRAY_OF_UBYTES -> { + 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) + } + TypeDefinition.LONG -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } + TypeDefinition.INT -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } + TypeDefinition.STRING -> { + paramsBuilder.append(paramDefinition.parameterName + separator) + } + } + } + + } + paramsBuilder.append(')') + return paramsBuilder.toString() + } + + + +} diff --git a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt index eefbc4d..0745001 100644 --- a/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt +++ b/kotlin-multiplatform-libsodium-generator/src/main/kotlin/com/ionspin/kotlin/crypto/generator/libsodium/generator/NativeLibsodiumGenerator.kt @@ -21,7 +21,7 @@ object NativeLibsodiumGenerator { for (commonClassDefinition in fileDefinition.commonClassList) { //Create type-aliases commonClassDefinition.innerClasses.forEach { - fileBuilder.addTypeAlias(createJvmInnerClassSpec(it, MultiplatformModifier.ACTUAL)) + fileBuilder.addTypeAlias(createNativeInnerClassSpec(it, MultiplatformModifier.ACTUAL)) } val commonClassSpec = createClass( @@ -36,7 +36,7 @@ object NativeLibsodiumGenerator { return file } - fun createJvmInnerClassSpec( + fun createNativeInnerClassSpec( innerClassDefinition: InnerClassDefinition, multiplatformModifier: MultiplatformModifier ): TypeAliasSpec { diff --git a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt index ae4a065..1c001d2 100644 --- a/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt +++ b/multiplatform-crypto-delegated/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt @@ -13,7 +13,6 @@ import org.khronos.webgl.set */ fun UByteArray.toUInt8Array() : Uint8Array { val uint8Result = Uint8Array(toByteArray().toTypedArray()) -// console.log("Uint8: $uint8Result") return uint8Result } @@ -23,7 +22,6 @@ fun Uint8Array.toUByteArray() : UByteArray { for (i in 0 until length) { result[i] = get(i).toUByte() } -// console.log("UbyteArray: ${result.joinToString()}") return result } diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt new file mode 100644 index 0000000..9cecbbd --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsUtil.kt @@ -0,0 +1,24 @@ +package ext.libsodium.com.ionspin.kotlin.crypto + +import org.khronos.webgl.Uint8Array +import org.khronos.webgl.get + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 02-Aug-2020 + */ +fun UByteArray.toUInt8Array() : Uint8Array { + val uint8Result = Uint8Array(toByteArray().toTypedArray()) + return uint8Result +} + + +fun Uint8Array.toUByteArray() : UByteArray { + val result = UByteArray(length) + for (i in 0 until length) { + result[i] = get(i).toUByte() + } + + return result +}