diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0695d61..49b17fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip diff --git a/library/build.gradle b/library/build.gradle index f1cfed1..a269b81 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -17,7 +17,7 @@ repositories { } dependencies { - compile project(':runtime') + compile project(':runtime-lite') compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" compile 'com.github.cretz.pbandk:protoc-gen-kotlin-jvm:0.3.0' compile 'com.squareup:kotlinpoet:1.0.1' diff --git a/library/src/main/kotlin/jp/co/panpanini/MessageGenerator.kt b/library/src/main/kotlin/jp/co/panpanini/MessageGenerator.kt index a26e019..a93e616 100644 --- a/library/src/main/kotlin/jp/co/panpanini/MessageGenerator.kt +++ b/library/src/main/kotlin/jp/co/panpanini/MessageGenerator.kt @@ -5,7 +5,6 @@ import com.improve_future.case_changer.toSnakeCase import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import pbandk.gen.File -import java.io.Serializable class MessageGenerator(private val file: File, private val kotlinTypeMappings: Map) { diff --git a/runtime-lite/build.gradle b/runtime-lite/build.gradle index 32a7ca5..1b74e2a 100644 --- a/runtime-lite/build.gradle +++ b/runtime-lite/build.gradle @@ -1,6 +1,4 @@ -apply plugin: 'kotlin' -apply plugin: 'org.jetbrains.kotlin.jvm' -apply plugin: 'guru.stefma.artifactorypublish' +apply plugin: 'kotlin-multiplatform' sourceCompatibility = 1.8 @@ -13,27 +11,26 @@ repositories { } -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - compile "com.google.protobuf:protobuf-lite:3.0.1" - testCompile group: 'junit', name: 'junit', version: '4.12' - testCompile('com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0') - testCompile("org.assertj:assertj-core:3.11.1") -} - -compileKotlin { - kotlinOptions.jvmTarget = "1.8" -} -compileTestKotlin { - kotlinOptions.jvmTarget = "1.8" -} +kotlin { + targets { + jvm() + } -artifactoryPublish { - groupId = 'jp.co.panpanini' - artifactId = 'protok-runtime-lite' - publishVersion = versionName() - artifactoryUrl = artifactoryUrl - artifactoryRepo = artifactoryRepo - artifactoryUser = artifactoryUsername - artifactoryKey = artifactoryPassword + sourceSets { + commonMain {} + commonTest {} + jvmMain { + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + implementation "com.google.protobuf:protobuf-lite:3.0.1" + } + } + jvmTest { + dependencies { + implementation group: 'junit', name: 'junit', version: '4.12' + implementation('com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0') + implementation("org.assertj:assertj-core:3.11.1") + } + } + } } \ No newline at end of file diff --git a/runtime-lite/src/main/kotlin/ByteArr.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ByteArr.kt similarity index 91% rename from runtime-lite/src/main/kotlin/ByteArr.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ByteArr.kt index 5783620..cb6de62 100644 --- a/runtime-lite/src/main/kotlin/ByteArr.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ByteArr.kt @@ -1,7 +1,5 @@ package jp.co.panpanini -import java.io.Serializable - class ByteArr(val array: ByteArray = ByteArray(0)) : Serializable { override fun equals(other: Any?) = other is ByteArr && array.contentEquals(other.array) override fun hashCode() = array.contentHashCode() diff --git a/runtime-lite/src/main/kotlin/Marshaller.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Marshaller.kt similarity index 100% rename from runtime-lite/src/main/kotlin/Marshaller.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Marshaller.kt diff --git a/runtime-lite/src/main/kotlin/Message.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Message.kt similarity index 77% rename from runtime-lite/src/main/kotlin/Message.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Message.kt index d587747..6b04077 100644 --- a/runtime-lite/src/main/kotlin/Message.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Message.kt @@ -1,17 +1,13 @@ package jp.co.panpanini -import java.io.InputStream -import java.io.Serializable - interface Message> : Serializable { fun protoUnmarshal(u: Unmarshaller): T fun protoUnmarshal(arr: ByteArray) = protoUnmarshal(Unmarshaller.fromByteArray(arr)) - fun protoUnmarshal(inputStream: InputStream) = protoUnmarshal(Unmarshaller(Reader(inputStream.readBytes()))) operator fun plus(other: T?): T val protoSize: Int fun protoMarshal(m: Marshaller) - fun protoMarshal(): ByteArray = Marshaller.allocate(protoSize).also(::protoMarshal).complete()!! + fun protoMarshal(): ByteArray = Marshaller.allocate(protoSize).also(::protoMarshal).complete() interface Companion> { fun protoUnmarshal(u: Unmarshaller): T @@ -25,5 +21,4 @@ interface Message> : Serializable { fun fromValue(value: Int): T } } -} - +} \ No newline at end of file diff --git a/runtime-lite/src/main/kotlin/Reader.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Reader.kt similarity index 99% rename from runtime-lite/src/main/kotlin/Reader.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Reader.kt index 8efdd76..45d4ce5 100644 --- a/runtime-lite/src/main/kotlin/Reader.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Reader.kt @@ -510,7 +510,7 @@ class Reader(private val byteArray: ByteArray) { * nothing is skipped. Otherwise, returns `true`. */ fun skipField(tag: Int): Boolean { - return when (com.google.protobuf.WireFormat.getTagWireType(tag)) { + return when (WireFormat.getTagWireType(tag)) { WireFormat.WIRETYPE_VARINT -> { skipRawVarint() true diff --git a/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Serializable.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Serializable.kt new file mode 100644 index 0000000..7376d5a --- /dev/null +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Serializable.kt @@ -0,0 +1,3 @@ +package jp.co.panpanini + +expect interface Serializable diff --git a/runtime-lite/src/main/kotlin/Sizer.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Sizer.kt similarity index 71% rename from runtime-lite/src/main/kotlin/Sizer.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Sizer.kt index 5d8b281..b7d4198 100644 --- a/runtime-lite/src/main/kotlin/Sizer.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Sizer.kt @@ -1,6 +1,5 @@ package jp.co.panpanini -import com.google.protobuf.CodedOutputStream object Sizer { fun tagSize(fieldNum: Int): Int { @@ -48,7 +47,30 @@ object Sizer { fun int64Size(value: Long) = uInt64Size(value) - fun uInt64Size(value: Long) = CodedOutputStream.computeUInt64SizeNoTag(value) + fun uInt64Size(value: Long): Int { + var value = value + // handle two popular special cases up front ... + if (value and (0L.inv() shl 7) == 0L) { + return 1 + } + if (value < 0L) { + return 10 + } + // ... leaving us with 8 remaining, which we can divide and conquer + var n = 2 + if (value and (0L.inv() shl 35) != 0L) { + n += 4 + value = value ushr 28 + } + if (value and (0L.inv() shl 21) != 0L) { + n += 2 + value = value ushr 14 + } + if (value and (0L.inv() shl 14) != 0L) { + n += 1 + } + return n + } fun bytesSize(value: ByteArray) = uInt32Size(value.size) + value.size @@ -72,7 +94,7 @@ object Sizer { fun boolSize(value: Boolean) = 1 - fun stringSize(value: String) = CodedOutputStream.computeStringSizeNoTag(value) + fun stringSize(value: String) = try { Utf8.encodedLength(value) } catch(e: Exception) { value.toByteArray().size } private fun Int.zigZagEncode() = (this shl 1) xor (this shr 31) private fun Long.zigZagEncode() = (this shl 1) xor (this shr 63) diff --git a/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ToByteArray.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ToByteArray.kt new file mode 100644 index 0000000..f51010f --- /dev/null +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/ToByteArray.kt @@ -0,0 +1,3 @@ +package jp.co.panpanini + +expect fun String.toByteArray(): ByteArray \ No newline at end of file diff --git a/runtime-lite/src/main/kotlin/UnknownField.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/UnknownField.kt similarity index 98% rename from runtime-lite/src/main/kotlin/UnknownField.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/UnknownField.kt index a484ef2..4cf8a5d 100644 --- a/runtime-lite/src/main/kotlin/UnknownField.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/UnknownField.kt @@ -1,8 +1,5 @@ package jp.co.panpanini -import java.io.Serializable - - data class UnknownField(val fieldNum: Int, val value: Value) : Serializable { constructor(fieldNum: Int, value: Long, fixed: Boolean = false) : this(fieldNum, if (fixed) Value.Fixed64(value) else Value.Varint(value)) diff --git a/runtime-lite/src/main/kotlin/Unmarshaller.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Unmarshaller.kt similarity index 97% rename from runtime-lite/src/main/kotlin/Unmarshaller.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Unmarshaller.kt index b262c2c..16a1eb6 100644 --- a/runtime-lite/src/main/kotlin/Unmarshaller.kt +++ b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Unmarshaller.kt @@ -54,7 +54,7 @@ class Unmarshaller(private val reader: Reader, private val discardUnknownFields: } val message = companion.protoUnmarshal(this) require(reader.isAtEnd) { - "Unable to completely read stream for message ${message::class.java}" + "Unable to completely read stream for message ${message::class}" } reader.popLimit(previousLimit) currentUnknownFields = unknownFields @@ -87,9 +87,9 @@ class Unmarshaller(private val reader: Reader, private val discardUnknownFields: } fun > readRepeatedMessage( - appendTo: List?, - companion: Message.Companion, - neverPacked: Boolean + appendTo: List?, + companion: Message.Companion, + neverPacked: Boolean ): List { return readRepeated(appendTo, neverPacked) { readMessage(companion) diff --git a/runtime-lite/src/main/kotlin/Utf8.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Utf8.kt similarity index 100% rename from runtime-lite/src/main/kotlin/Utf8.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Utf8.kt diff --git a/runtime-lite/src/main/kotlin/Writer.kt b/runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Writer.kt similarity index 100% rename from runtime-lite/src/main/kotlin/Writer.kt rename to runtime-lite/src/commonMain/kotlin/jp/co/panpanini/Writer.kt diff --git a/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Message.kt b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Message.kt new file mode 100644 index 0000000..0473b96 --- /dev/null +++ b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Message.kt @@ -0,0 +1,7 @@ +package jp.co.panpanini + +import java.io.InputStream + +fun > Message.protoUnmarshal(inputStream: InputStream) = protoUnmarshal( + Unmarshaller(Reader(inputStream.readBytes())) +) \ No newline at end of file diff --git a/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Serializable.kt b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Serializable.kt new file mode 100644 index 0000000..4e6a806 --- /dev/null +++ b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/Serializable.kt @@ -0,0 +1,3 @@ +package jp.co.panpanini + +actual typealias Serializable = java.io.Serializable diff --git a/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/toByteArray.kt b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/toByteArray.kt new file mode 100644 index 0000000..8a45b82 --- /dev/null +++ b/runtime-lite/src/jvmMain/kotlin/jp/co/panpanini/toByteArray.kt @@ -0,0 +1,3 @@ +package jp.co.panpanini + +actual fun String.toByteArray(): ByteArray = this.toByteArray(Charsets.UTF_8) \ No newline at end of file diff --git a/runtime-lite/src/test/kotlin/MarshallerTest.kt b/runtime-lite/src/jvmTest/kotlin/MarshallerTest.kt similarity index 100% rename from runtime-lite/src/test/kotlin/MarshallerTest.kt rename to runtime-lite/src/jvmTest/kotlin/MarshallerTest.kt diff --git a/runtime-lite/src/test/kotlin/SizerTest.kt b/runtime-lite/src/jvmTest/kotlin/SizerTest.kt similarity index 100% rename from runtime-lite/src/test/kotlin/SizerTest.kt rename to runtime-lite/src/jvmTest/kotlin/SizerTest.kt diff --git a/runtime-lite/src/test/kotlin/UnmarshallerTest.kt b/runtime-lite/src/jvmTest/kotlin/UnmarshallerTest.kt similarity index 100% rename from runtime-lite/src/test/kotlin/UnmarshallerTest.kt rename to runtime-lite/src/jvmTest/kotlin/UnmarshallerTest.kt diff --git a/runtime-lite/src/test/kotlin/WriterTest.kt b/runtime-lite/src/jvmTest/kotlin/WriterTest.kt similarity index 100% rename from runtime-lite/src/test/kotlin/WriterTest.kt rename to runtime-lite/src/jvmTest/kotlin/WriterTest.kt diff --git a/runtime-lite/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/runtime-lite/src/jvmTest/resources/mockito-extensions/org.mockito.plugins.MockMaker similarity index 100% rename from runtime-lite/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker rename to runtime-lite/src/jvmTest/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/sample/README.md b/sample/README.md new file mode 100644 index 0000000..73034f3 --- /dev/null +++ b/sample/README.md @@ -0,0 +1,6 @@ +# Sample + +A sample project to show how to use the protok library to generate Kotlin classes and how to use the generated classes themselves. + +## usage +Use the gradle task `generateProto` to generate the required Kotlin protocol buffer implementations. This expects protoc to be installed and available on the PATH. \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle new file mode 100644 index 0000000..4a38bf9 --- /dev/null +++ b/sample/build.gradle @@ -0,0 +1,29 @@ +plugins { + id 'java' + id 'org.jetbrains.kotlin.jvm' +} + +version '1.0.0' + +repositories { + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib" + testCompile group: 'junit', name: 'junit', version: '4.12' + + implementation project(":runtime-lite") +} + +task generateProto(type: Exec) { + dependsOn(":library:installDist") + commandLine( + 'protoc', + "--plugin=protoc-gen-custom=${rootDir}/library/build/install/protoc-gen-kotlin/bin/protoc-gen-kotlin", + "--custom_out=${projectDir}/src/main/kotlin/", + "--proto_path=${projectDir}/src/main/proto/", + "user.proto" + ) + +} \ No newline at end of file diff --git a/sample/src/main/kotlin/Sample.kt b/sample/src/main/kotlin/Sample.kt new file mode 100644 index 0000000..e902537 --- /dev/null +++ b/sample/src/main/kotlin/Sample.kt @@ -0,0 +1,38 @@ +package main.kotlin + +class Sample(private val name: String) { + companion object { + private var LATEST_ID = 1 + } + + fun generateUser(): User { + return User.with { + id = LATEST_ID++ + name = this@Sample.name + programingLanguages = listOf( + ProgramingLanguage.with { + name = "Kotlin" + yearsLearning(5) + }, + ProgramingLanguage.with { + name = "Java" + yearsLearning(10) + } + ) + } + } + +} + + +fun main() { + val sample = Sample("Panini") + + val user = sample.generateUser() + + println(user) + println(user.name) + user.programingLanguages.forEach { + println("learned ${it.name} for ${it.yearsLearning} years") + } +} \ No newline at end of file diff --git a/sample/src/main/proto/user.proto b/sample/src/main/proto/user.proto new file mode 100644 index 0000000..5cd47b0 --- /dev/null +++ b/sample/src/main/proto/user.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package proto; + +message User { + int32 id = 1; + string name = 2; + repeated ProgramingLanguage programingLanguages = 3; +} + +message ProgramingLanguage { + string name = 1; + int32 yearsLearning = 2; +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 280728b..e03c584 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ -include ':library', ':retrofit-converter', ':runtime', ':runtime-lite', ':retrofit-converter-lite' +include ':library', ':retrofit-converter', ':runtime', ':runtime-lite', ':retrofit-converter-lite',':sample' rootProject.name = 'protok'