Skip to content

Commit 56372ad

Browse files
authored
gRPC: Support initial proto generation for common (JVM and Native) (#415)
* grpc-native: First message generation Signed-off-by: Johannes Zottele <[email protected]> * grpc-native: Support for repeated fields in Message generation Signed-off-by: Johannes Zottele <[email protected]> * grpc-native: Remove guards in generated kotlin Signed-off-by: Johannes Zottele <[email protected]> * grpc-native: Move internal decode/encoding into grpc.pb package and move common proto generation to commonTest Signed-off-by: Johannes Zottele <[email protected]> * grpc-native: Address PR comments Signed-off-by: Johannes Zottele <[email protected]> * grpc-native: Rename ProtosTest class Signed-off-by: Johannes Zottele <[email protected]> --------- Signed-off-by: Johannes Zottele <[email protected]>
1 parent 75f8b3c commit 56372ad

File tree

39 files changed

+1036
-289
lines changed

39 files changed

+1036
-289
lines changed

gradle-plugin/src/main/kotlin/kotlinx/rpc/proto/DefaultProtoSourceSet.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ import kotlinx.rpc.buf.tasks.BufGenerateTask
88
import kotlinx.rpc.util.findOrCreate
99
import kotlinx.rpc.util.withKotlinJvmExtension
1010
import kotlinx.rpc.util.withKotlinKmpExtension
11-
import org.gradle.api.Action
12-
import org.gradle.api.GradleException
13-
import org.gradle.api.NamedDomainObjectFactory
14-
import org.gradle.api.NamedDomainObjectProvider
15-
import org.gradle.api.Project
11+
import org.gradle.api.*
1612
import org.gradle.api.file.SourceDirectorySet
1713
import org.gradle.api.provider.ListProperty
1814
import org.gradle.api.provider.Property
@@ -102,9 +98,11 @@ internal fun Project.createProtoExtensions() {
10298
project.withKotlinKmpExtension {
10399
findOrCreateAndConfigure("jvmMain", null)
104100
findOrCreateAndConfigure("jvmTest", null)
101+
findOrCreateAndConfigure("commonMain", null)
102+
findOrCreateAndConfigure("commonTest", null)
105103

106104
sourceSets.configureEach {
107-
if (name == "jvmMain" || name == "jvmTest") {
105+
if (name == "jvmMain" || name == "jvmTest" || name == "commonMain" || name == "commonTest") {
108106
findOrCreateAndConfigure(name, this)
109107
}
110108
}

grpc/grpc-core/build.gradle.kts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import kotlinx.rpc.buf.tasks.BufGenerateTask
66
import kotlinx.rpc.proto.kotlinMultiplatform
7-
import org.gradle.kotlin.dsl.withType
87
import org.gradle.internal.extensions.stdlib.capitalized
98
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
109
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
@@ -123,8 +122,8 @@ kotlin {
123122
)
124123
}
125124

126-
val libUpbTask = "cinterop${libprotowire.name.capitalized()}${it.targetName.capitalized()}"
127-
tasks.named(libUpbTask, CInteropProcess::class) {
125+
val libProtowireTask = "cinterop${libprotowire.name.capitalized()}${it.targetName.capitalized()}"
126+
tasks.named(libProtowireTask, CInteropProcess::class) {
128127
dependsOn(buildGrpcppCLib)
129128
}
130129

@@ -139,8 +138,15 @@ protoSourceSets {
139138
exclude("exclude/**")
140139
}
141140
}
141+
142+
commonTest {
143+
proto {
144+
exclude("exclude/**")
145+
}
146+
}
142147
}
143148

149+
144150
rpc {
145151
grpc {
146152
val globalRootDir: String by extra
@@ -152,6 +158,15 @@ rpc {
152158
}
153159

154160
project.tasks.withType<BufGenerateTask>().configureEach {
161+
162+
// TODO: Remove this once we remove JVM generation
163+
// Set compile for common(native) option
164+
if (name.endsWith("CommonTest")) {
165+
protocPlugins.kotlinMultiplatform {
166+
options.put("targetMode", "common")
167+
}
168+
}
169+
155170
if (name.endsWith("Test")) {
156171
dependsOn(gradle.includedBuild("protoc-gen").task(":jar"))
157172
}

grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/internal/WireEncoder.kt

Lines changed: 0 additions & 54 deletions
This file was deleted.

grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/internal/WireSize.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/internal/readPacked.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
package kotlinx.rpc.grpc.internal
66

7-
import kotlinx.io.Buffer
7+
import kotlinx.rpc.grpc.pb.WireDecoder
88

99
internal expect fun WireDecoder.pushLimit(byteLen: Int): Int
1010
internal expect fun WireDecoder.popLimit(limit: Int)

grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/internal/KTag.kt renamed to grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/pb/KTag.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
package kotlinx.rpc.grpc.internal
5+
package kotlinx.rpc.grpc.pb
66

7-
import kotlinx.rpc.grpc.internal.KTag.Companion.K_TAG_TYPE_BITS
7+
import kotlinx.rpc.internal.utils.InternalRpcApi
88

9-
internal enum class WireType {
9+
@InternalRpcApi
10+
public enum class WireType {
1011
VARINT, // 0
1112
FIXED64, // 1
1213
LENGTH_DELIMITED, // 2
@@ -15,13 +16,14 @@ internal enum class WireType {
1516
FIXED32, // 5
1617
}
1718

18-
internal data class KTag(val fieldNr: Int, val wireType: WireType) {
19+
@InternalRpcApi
20+
public data class KTag(val fieldNr: Int, val wireType: WireType) {
1921

2022
init {
2123
check(isValidFieldNr(fieldNr)) { "Invalid field number: $fieldNr" }
2224
}
2325

24-
companion object {
26+
internal companion object {
2527
// Number of bits in a tag which identify the wire type.
2628
const val K_TAG_TYPE_BITS: Int = 3;
2729

@@ -31,7 +33,7 @@ internal data class KTag(val fieldNr: Int, val wireType: WireType) {
3133
}
3234

3335
internal fun KTag.toRawKTag(): UInt {
34-
return (fieldNr.toUInt() shl K_TAG_TYPE_BITS) or wireType.ordinal.toUInt()
36+
return (fieldNr.toUInt() shl KTag.Companion.K_TAG_TYPE_BITS) or wireType.ordinal.toUInt()
3537
}
3638

3739
internal fun KTag.Companion.fromOrNull(rawKTag: UInt): KTag? {

grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/internal/WireDecoder.kt renamed to grpc/grpc-core/src/commonMain/kotlin/kotlinx/rpc/grpc/pb/WireDecoder.kt

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5-
package kotlinx.rpc.grpc.internal
5+
package kotlinx.rpc.grpc.pb
66

77
import kotlinx.io.Buffer
8+
import kotlinx.rpc.internal.utils.InternalRpcApi
89

910
// TODO: Evaluate if this buffer size is suitable for all targets (KRPC-186)
1011
// maximum buffer size to allocate as contiguous memory in bytes
@@ -36,40 +37,45 @@ internal const val MAX_PACKED_BULK_SIZE: Int = 1_000_000
3637
* }
3738
* ```
3839
*/
39-
internal interface WireDecoder : AutoCloseable {
40-
fun hadError(): Boolean
41-
fun readTag(): KTag?
42-
fun readBool(): Boolean
43-
fun readInt32(): Int
44-
fun readInt64(): Long
45-
fun readUInt32(): UInt
46-
fun readUInt64(): ULong
47-
fun readSInt32(): Int
48-
fun readSInt64(): Long
49-
fun readFixed32(): UInt
50-
fun readFixed64(): ULong
51-
fun readSFixed32(): Int
52-
fun readSFixed64(): Long
53-
fun readFloat(): Float
54-
fun readDouble(): Double
40+
@InternalRpcApi
41+
public interface WireDecoder : AutoCloseable {
42+
public fun hadError(): Boolean
5543

56-
fun readEnum(): Int
57-
fun readString(): String
58-
fun readBytes(): ByteArray
59-
fun readPackedBool(): List<Boolean>
60-
fun readPackedInt32(): List<Int>
61-
fun readPackedInt64(): List<Long>
62-
fun readPackedSInt32(): List<Int>
63-
fun readPackedSInt64(): List<Long>
64-
fun readPackedUInt32(): List<UInt>
65-
fun readPackedUInt64(): List<ULong>
66-
fun readPackedFixed32(): List<UInt>
67-
fun readPackedFixed64(): List<ULong>
68-
fun readPackedSFixed32(): List<Int>
69-
fun readPackedSFixed64(): List<Long>
70-
fun readPackedFloat(): List<Float>
71-
fun readPackedDouble(): List<Double>
72-
fun readPackedEnum(): List<Int>
44+
/**
45+
* When the read tag is null, it indicates EOF and the parser may stop at this point.
46+
*/
47+
public fun readTag(): KTag?
48+
public fun readBool(): Boolean
49+
public fun readInt32(): Int
50+
public fun readInt64(): Long
51+
public fun readUInt32(): UInt
52+
public fun readUInt64(): ULong
53+
public fun readSInt32(): Int
54+
public fun readSInt64(): Long
55+
public fun readFixed32(): UInt
56+
public fun readFixed64(): ULong
57+
public fun readSFixed32(): Int
58+
public fun readSFixed64(): Long
59+
public fun readFloat(): Float
60+
public fun readDouble(): Double
61+
62+
public fun readEnum(): Int
63+
public fun readString(): String
64+
public fun readBytes(): ByteArray
65+
public fun readPackedBool(): List<Boolean>
66+
public fun readPackedInt32(): List<Int>
67+
public fun readPackedInt64(): List<Long>
68+
public fun readPackedSInt32(): List<Int>
69+
public fun readPackedSInt64(): List<Long>
70+
public fun readPackedUInt32(): List<UInt>
71+
public fun readPackedUInt64(): List<ULong>
72+
public fun readPackedFixed32(): List<UInt>
73+
public fun readPackedFixed64(): List<ULong>
74+
public fun readPackedSFixed32(): List<Int>
75+
public fun readPackedSFixed64(): List<Long>
76+
public fun readPackedFloat(): List<Float>
77+
public fun readPackedDouble(): List<Double>
78+
public fun readPackedEnum(): List<Int>
7379
}
7480

7581
/**
@@ -82,4 +88,4 @@ internal interface WireDecoder : AutoCloseable {
8288
*
8389
* @param source The buffer containing the encoded wire-format data.
8490
*/
85-
internal expect fun WireDecoder(source: Buffer): WireDecoder
91+
internal expect fun WireDecoder(source: Buffer): WireDecoder
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc.pb
6+
7+
import kotlinx.io.Sink
8+
import kotlinx.rpc.internal.utils.InternalRpcApi
9+
10+
/**
11+
* A platform-specific class that encodes values into protobuf's wire format.
12+
*
13+
* If one `write*()` method returns false, the encoding of the value failed
14+
* and no further encodings can be performed on this [WireEncoder].
15+
*
16+
* [flush] must be called to ensure that all data is written to the [Sink].
17+
*/
18+
@InternalRpcApi
19+
@OptIn(ExperimentalUnsignedTypes::class)
20+
public interface WireEncoder {
21+
public fun flush()
22+
public fun writeBool(fieldNr: Int, value: Boolean): Boolean
23+
public fun writeInt32(fieldNr: Int, value: Int): Boolean
24+
public fun writeInt64(fieldNr: Int, value: Long): Boolean
25+
public fun writeUInt32(fieldNr: Int, value: UInt): Boolean
26+
public fun writeUInt64(fieldNr: Int, value: ULong): Boolean
27+
public fun writeSInt32(fieldNr: Int, value: Int): Boolean
28+
public fun writeSInt64(fieldNr: Int, value: Long): Boolean
29+
public fun writeFixed32(fieldNr: Int, value: UInt): Boolean
30+
public fun writeFixed64(fieldNr: Int, value: ULong): Boolean
31+
public fun writeSFixed32(fieldNr: Int, value: Int): Boolean
32+
public fun writeSFixed64(fieldNr: Int, value: Long): Boolean
33+
public fun writeFloat(fieldNr: Int, value: Float): Boolean
34+
public fun writeDouble(fieldNr: Int, value: Double): Boolean
35+
public fun writeEnum(fieldNr: Int, value: Int): Boolean
36+
public fun writeBytes(fieldNr: Int, value: ByteArray): Boolean
37+
public fun writeString(fieldNr: Int, value: String): Boolean
38+
public fun writePackedBool(fieldNr: Int, value: List<Boolean>, fieldSize: Int): Boolean
39+
public fun writePackedInt32(fieldNr: Int, value: List<Int>, fieldSize: Int): Boolean
40+
public fun writePackedInt64(fieldNr: Int, value: List<Long>, fieldSize: Int): Boolean
41+
public fun writePackedUInt32(fieldNr: Int, value: List<UInt>, fieldSize: Int): Boolean
42+
public fun writePackedUInt64(fieldNr: Int, value: List<ULong>, fieldSize: Int): Boolean
43+
public fun writePackedSInt32(fieldNr: Int, value: List<Int>, fieldSize: Int): Boolean
44+
public fun writePackedSInt64(fieldNr: Int, value: List<Long>, fieldSize: Int): Boolean
45+
public fun writePackedFixed32(fieldNr: Int, value: List<UInt>): Boolean
46+
public fun writePackedFixed64(fieldNr: Int, value: List<ULong>): Boolean
47+
public fun writePackedSFixed32(fieldNr: Int, value: List<Int>): Boolean
48+
public fun writePackedSFixed64(fieldNr: Int, value: List<Long>): Boolean
49+
public fun writePackedFloat(fieldNr: Int, value: List<Float>): Boolean
50+
public fun writePackedDouble(fieldNr: Int, value: List<Double>): Boolean
51+
public fun writePackedEnum(fieldNr: Int, value: List<Int>, fieldSize: Int): Boolean =
52+
writePackedInt32(fieldNr, value, fieldSize)
53+
}
54+
55+
56+
internal expect fun WireEncoder(sink: Sink): WireEncoder

0 commit comments

Comments
 (0)