Skip to content

Commit bfb5b1d

Browse files
committed
pure kotlin dependency-free Marshaller/Unmarshaller and native
This provides native variants for all the components. Code is adapted from java protobuf code.
1 parent cf8cb83 commit bfb5b1d

File tree

28 files changed

+1061
-567
lines changed

28 files changed

+1061
-567
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.3.11'
2+
ext.kotlin_version = '1.3.20'
33
repositories {
44
mavenCentral()
55
maven {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright 2019 Google Inc. All rights reserved.
2+
// https://developers.google.com/protocol-buffers/
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following disclaimer
12+
// in the documentation and/or other materials provided with the
13+
// distribution.
14+
// * Neither the name of Google Inc. nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
package pbandk.conformance
31+
32+
import platform.posix.*
33+
import kotlinx.cinterop.cstr
34+
import kotlinx.cinterop.usePinned
35+
import kotlinx.cinterop.addressOf
36+
37+
actual object Platform {
38+
actual fun stderrPrintln(str: String) {
39+
val strn = str + "\n"
40+
val cstr = strn.cstr
41+
write(2, cstr, cstr.size.toULong())
42+
}
43+
44+
actual fun stdinReadIntLE() = ByteArray(4).let {
45+
if (readBytes(0, it) != 4) null else
46+
it.foldRight(0) { byte, acc ->
47+
(acc shl 8) or (byte.toInt() and 0xff)
48+
}
49+
}
50+
51+
private fun readBytes(fd: Int, arr: ByteArray): Int {
52+
arr.usePinned {
53+
return read(fd, it.addressOf(0), arr.size.toULong()).toInt()
54+
}
55+
}
56+
57+
actual fun stdinReadFull(arr: ByteArray) =
58+
require(readBytes(0, arr) == arr.size) { "Unable to read full byte array" }
59+
60+
actual fun stdoutWriteIntLE(v: Int) =
61+
stdoutWriteFull (ByteArray(4) { (v shr (8 * it)).toByte() })
62+
63+
actual fun stdoutWriteFull(arr: ByteArray) {
64+
arr.usePinned {
65+
write(1, it.addressOf(0), arr.size.toULong())
66+
}
67+
}
68+
69+
actual inline fun <T> doTry(fn: () -> T, errFn: (Any) -> T) = try { fn() } catch (e: Exception) { errFn(e) }
70+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
fun main(args: Array<String>) {
3+
pbandk.conformance.main(args)
4+
}

protoc-gen-kotlin/protoc-gen-kotlin-common/src/main/kotlin/pbandk/gen/Main.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ inline fun debug(fn: () -> String) { if (logDebug) Platform.stderrPrintln(fn())
88

99
fun main(args: Array<String>) {
1010
// Read the request from stdin and write response into stdout
11-
Platform.stdoutWriteResponse(runGenerator(Platform.stdinReadRequest()))
11+
try {
12+
Platform.stdoutWriteResponse(runGenerator(Platform.stdinReadRequest()))
13+
} catch (e: Exception) {
14+
Platform.stderrPrintln("Caught exception $e")
15+
throw e
16+
}
1217
}
1318

1419
fun runGenerator(request: CodeGeneratorRequest): CodeGeneratorResponse {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2019 Google Inc. All rights reserved.
2+
// https://developers.google.com/protocol-buffers/
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following disclaimer
12+
// in the documentation and/or other materials provided with the
13+
// distribution.
14+
// * Neither the name of Google Inc. nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
package pbandk.gen
31+
32+
import pbandk.gen.pb.CodeGeneratorRequest
33+
import pbandk.gen.pb.CodeGeneratorResponse
34+
import platform.posix.*
35+
import kotlinx.cinterop.cstr
36+
import kotlinx.cinterop.usePinned
37+
import kotlinx.cinterop.addressOf
38+
39+
actual object Platform {
40+
actual fun stderrPrintln(str: String) {
41+
val strn = str + "\n"
42+
val cstr = strn.cstr
43+
write(2, cstr, cstr.size.toULong())
44+
}
45+
46+
private fun readBytes(fd: Int): ByteArray {
47+
var ret = byteArrayOf()
48+
val buf = ByteArray(8192)
49+
buf.usePinned {
50+
while (true) {
51+
val res = read(fd, it.addressOf(0), buf.size.toULong())
52+
if (res <= 0)
53+
break
54+
ret += buf.sliceArray(0 until res.toInt())
55+
}
56+
}
57+
return ret
58+
}
59+
60+
actual fun stdinReadRequest(): CodeGeneratorRequest {
61+
val buf = readBytes(0)
62+
try {
63+
val cg = CodeGeneratorRequest.protoUnmarshal(buf)
64+
return cg
65+
} catch (e: Exception) {
66+
stderrPrintln("Unmarshall exception: $e")
67+
throw e
68+
}
69+
}
70+
71+
actual fun stdoutWriteResponse(resp: CodeGeneratorResponse) {
72+
val buf = resp.protoMarshal()
73+
buf.usePinned {
74+
write(1, it.addressOf(0), buf.size.toULong())
75+
}
76+
}
77+
78+
actual fun serviceGenerator(cliParams: Map<String, String>): ServiceGenerator? = null
79+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
fun main(args: Array<String>) {
3+
pbandk.gen.main(args)
4+
}
Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,32 @@
11
package pbandk
22

3-
expect class Marshaller {
4-
5-
fun writeTag(tag: Int): Marshaller
6-
fun writeDouble(value: Double)
7-
fun writeFloat(value: Float)
8-
fun writeInt32(value: Int)
9-
fun writeInt64(value: Long)
10-
fun writeUInt32(value: Int)
11-
fun writeUInt64(value: Long)
12-
fun writeSInt32(value: Int)
13-
fun writeSInt64(value: Long)
14-
fun writeFixed32(value: Int)
15-
fun writeFixed64(value: Long)
16-
fun writeSFixed32(value: Int)
17-
fun writeSFixed64(value: Long)
18-
fun writeBool(value: Boolean)
19-
fun writeString(value: String)
20-
fun writeBytes(value: ByteArr)
21-
fun writeEnum(value: Message.Enum)
22-
fun writeMessage(value: Message<*>)
23-
fun writeUnknownFields(fields: Map<Int, UnknownField>)
24-
fun <T> writePackedRepeated(list: List<T>, sizeFn: (T) -> Int, writeFn: (T) -> Unit)
25-
fun <K, V, T : Message<T>> writeMap(
26-
tag: Int,
27-
map: Map<K, V>,
28-
createEntry: (K, V, Map<Int, pbandk.UnknownField>) -> T
29-
)
30-
31-
// May not return a value if wasn't created with allocate
32-
fun complete(): ByteArray?
3+
class ByteArrayMarshallerOutputStream(private val backingBytes: ByteArray)
4+
: pbandk.impl.MarshallerOutputStream {
5+
override fun write(arr: ByteArray, offset: Int, len: Int) {
6+
arr.copyInto(backingBytes, pos, offset, offset + len)
7+
pos += len
8+
}
9+
10+
private var pos = 0
11+
12+
fun complete() = backingBytes.sliceArray(0 until pos)
3313

3414
companion object {
35-
fun allocate(size: Int): Marshaller
15+
fun allocate(size: Int) = ByteArrayMarshallerOutputStream(ByteArray(size))
3616
}
37-
}
17+
}
18+
19+
class ByteArrayMarshaller(val stream: ByteArrayMarshallerOutputStream)
20+
: pbandk.impl.Marshaller(stream = stream) {
21+
22+
fun complete() = stream.complete()
23+
24+
companion object {
25+
fun allocate(size: Int) = ByteArrayMarshaller(
26+
ByteArrayMarshallerOutputStream.allocate(size))
27+
}
28+
}
29+
30+
typealias Marshaller = pbandk.impl.Marshaller
31+
typealias Unmarshaller = pbandk.impl.Unmarshaller
32+
typealias Sizer = pbandk.impl.Sizer

runtime/runtime-common/src/main/kotlin/pbandk/Message.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package pbandk
33
interface Message<T : Message<T>> {
44
operator fun plus(other: T?): T
55
val protoSize: Int
6-
fun protoMarshal(m: Marshaller)
7-
fun protoMarshal() = Marshaller.allocate(protoSize).also(::protoMarshal).complete()!!
6+
fun protoMarshal(m: pbandk.impl.Marshaller)
7+
fun protoMarshal() = ByteArrayMarshaller.allocate(protoSize).also(::protoMarshal).complete()
88

99
interface Companion<T : Message<T>> {
10-
fun protoUnmarshal(u: Unmarshaller): T
11-
fun protoUnmarshal(arr: ByteArray) = protoUnmarshal(Unmarshaller.fromByteArray(arr))
10+
fun protoUnmarshal(u: pbandk.impl.Unmarshaller): T
11+
fun protoUnmarshal(arr: ByteArray) = protoUnmarshal(
12+
pbandk.impl.Unmarshaller.fromByteArray(arr))
1213
}
1314

1415
interface Enum {

runtime/runtime-common/src/main/kotlin/pbandk/Sizer.kt

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

runtime/runtime-common/src/main/kotlin/pbandk/UnknownField.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package pbandk
22

3+
import pbandk.impl.Sizer
4+
35
data class UnknownField(val fieldNum: Int, val value: Value) {
46
constructor(fieldNum: Int, value: Long, fixed: Boolean = false) :
57
this(fieldNum, if (fixed) Value.Fixed64(value) else Value.Varint(value))

0 commit comments

Comments
 (0)