Skip to content

Commit 939ed80

Browse files
Jozott00Mr3zee
authored andcommitted
grpc-native: Change packed input value type to List
Signed-off-by: Johannes Zottele <[email protected]>
1 parent d62bce3 commit 939ed80

File tree

7 files changed

+114
-62
lines changed

7 files changed

+114
-62
lines changed

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

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

55
package kotlinx.rpc.grpc.internal
66

7+
import kotlinx.rpc.grpc.internal.KTag.Companion.K_TAG_TYPE_BITS
8+
79
internal enum class WireType {
810
VARINT, // 0
911
FIXED64, // 1
@@ -22,11 +24,16 @@ internal data class KTag(val fieldNr: Int, val wireType: WireType) {
2224
companion object {
2325
// Number of bits in a tag which identify the wire type.
2426
const val K_TAG_TYPE_BITS: Int = 3;
27+
2528
// Mask for those bits. (just 0b111)
2629
val K_TAG_TYPE_MASK: UInt = (1u shl K_TAG_TYPE_BITS) - 1u
2730
}
2831
}
2932

33+
internal fun KTag.toRawKTag(): UInt {
34+
return (fieldNr.toUInt() shl K_TAG_TYPE_BITS) or wireType.ordinal.toUInt()
35+
}
36+
3037
internal fun KTag.Companion.from(rawKTag: UInt): KTag? {
3138
val type = (rawKTag and K_TAG_TYPE_MASK).toInt()
3239
val field = (rawKTag shr K_TAG_TYPE_BITS).toInt()

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ internal interface WireEncoder {
3333
fun writeEnum(fieldNr: Int, value: Int): Boolean
3434
fun writeBytes(fieldNr: Int, value: ByteArray): Boolean
3535
fun writeString(fieldNr: Int, value: String): Boolean
36-
fun writePackedFixed32(fieldNr: Int, value: UIntArray): Boolean
37-
fun writePackedFixed64(fieldNr: Int, value: ULongArray): Boolean
38-
fun writePackedSFixed32(fieldNr: Int, value: IntArray): Boolean
39-
fun writePackedSFixed64(fieldNr: Int, value: LongArray): Boolean
40-
fun writePackedFloat(fieldNr: Int, value: FloatArray): Boolean
41-
fun writePackedDouble(fieldNr: Int, value: DoubleArray): Boolean
36+
fun writePackedFixed32(fieldNr: Int, value: List<UInt>): Boolean
37+
fun writePackedFixed64(fieldNr: Int, value: List<ULong>): Boolean
38+
fun writePackedSFixed32(fieldNr: Int, value: List<Int>): Boolean
39+
fun writePackedSFixed64(fieldNr: Int, value: List<Long>): Boolean
40+
fun writePackedFloat(fieldNr: Int, value: List<Float>): Boolean
41+
fun writePackedDouble(fieldNr: Int, value: List<Double>): Boolean
4242
}
4343

4444

grpc/grpc-core/src/nativeMain/kotlin/kotlinx/rpc/grpc/internal/WireDecoder.native.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import kotlinx.io.Buffer
1010
import libprotowire.*
1111
import kotlin.experimental.ExperimentalNativeApi
1212
import kotlin.math.min
13+
import kotlin.native.ref.createCleaner
1314

1415
// maximum buffer size to allocate as contiguous memory in bytes
1516
private const val MAX_PACKED_BULK_SIZE: Int = 1_000_000
@@ -44,14 +45,17 @@ internal class WireDecoderNative(private val source: Buffer) : WireDecoder {
4445
pw_decoder_new(zeroCopyCInput)
4546
?: error("Failed to create proto wire decoder")
4647
}
48+
49+
val rawCleaner = createCleaner(raw) {
50+
pw_decoder_delete(it)
51+
}
4752

4853

4954
override fun close() {
50-
// delete the underlying decoder.
51-
// this will also fix the position in the source buffer
55+
// this will fix the position in the source buffer
5256
// (done by deconstructor of CodedInputStream)
53-
pw_decoder_delete(raw)
54-
// close zero inputs on close
57+
pw_decoder_close(raw)
58+
5559
zeroCopyInput.get().close()
5660
zeroCopyInput.dispose()
5761
}
@@ -243,7 +247,7 @@ internal class WireDecoderNative(private val source: Buffer) : WireDecoder {
243247
Pinned<DoubleArray>::addressOf,
244248
DoubleArray::asList,
245249
)
246-
250+
247251
/*
248252
* Based on the length of the packed repeated field, one of two list strategies is chosen.
249253
* If the length is less or equal a specific threshold (MAX_PACKED_BULK_SIZE),

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

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -125,46 +125,44 @@ internal class WireEncoderNative(private val sink: Sink) : WireEncoder {
125125
}
126126
}
127127

128-
override fun writePackedFixed32(fieldNr: Int, value: UIntArray) =
129-
writePackedInternal(fieldNr, value, UIntArray::size, UInt.SIZE_BYTES)
130-
{ it.addressOf(0) }
128+
override fun writePackedFixed32(fieldNr: Int, value: List<UInt>) =
129+
writePackedInternal(fieldNr, value, UInt.SIZE_BYTES, ::pw_encoder_write_fixed32_no_tag)
131130

132-
override fun writePackedFixed64(fieldNr: Int, value: ULongArray) =
133-
writePackedInternal(fieldNr, value, ULongArray::size, ULong.SIZE_BYTES)
134-
{ it.addressOf(0) }
131+
override fun writePackedFixed64(fieldNr: Int, value: List<ULong>) =
132+
writePackedInternal(fieldNr, value, ULong.SIZE_BYTES, ::pw_encoder_write_fixed64_no_tag)
135133

136-
override fun writePackedSFixed32(fieldNr: Int, value: IntArray) =
137-
writePackedInternal(fieldNr, value, IntArray::size, Int.SIZE_BYTES)
138-
{ it.addressOf(0) }
134+
override fun writePackedSFixed32(fieldNr: Int, value: List<Int>) =
135+
writePackedInternal(fieldNr, value, Int.SIZE_BYTES, ::pw_encoder_write_sfixed32_no_tag)
139136

140-
override fun writePackedSFixed64(fieldNr: Int, value: LongArray) =
141-
writePackedInternal(fieldNr, value, LongArray::size, Long.SIZE_BYTES)
142-
{ it.addressOf(0) }
137+
override fun writePackedSFixed64(fieldNr: Int, value: List<Long>) =
138+
writePackedInternal(fieldNr, value, Long.SIZE_BYTES, ::pw_encoder_write_sfixed64_no_tag)
143139

144-
override fun writePackedFloat(fieldNr: Int, value: FloatArray) =
145-
writePackedInternal(fieldNr, value, FloatArray::size, Float.SIZE_BYTES)
146-
{ it.addressOf(0) }
140+
override fun writePackedFloat(fieldNr: Int, value: List<Float>) =
141+
writePackedInternal(fieldNr, value, Float.SIZE_BYTES, ::pw_encoder_write_float_no_tag)
147142

148-
override fun writePackedDouble(fieldNr: Int, value: DoubleArray) =
149-
writePackedInternal(fieldNr, value, DoubleArray::size, Double.SIZE_BYTES)
150-
{ it.addressOf(0) }
143+
override fun writePackedDouble(fieldNr: Int, value: List<Double>) =
144+
writePackedInternal(fieldNr, value, Double.SIZE_BYTES, ::pw_encoder_write_double_no_tag)
151145
}
152146

153147
internal actual fun WireEncoder(sink: Sink): WireEncoder = WireEncoderNative(sink)
154148

155149

156150
@OptIn(ExperimentalForeignApi::class)
157-
private inline fun <A : Any> WireEncoderNative.writePackedInternal(
151+
private inline fun <T> WireEncoderNative.writePackedInternal(
158152
fieldNr: Int,
159-
value: A,
160-
crossinline sizeOf: A.() -> Int,
161-
sizeBytes: Int,
162-
crossinline ptr: (Pinned<A>) -> COpaquePointer
153+
value: List<T>,
154+
byteSize: Int,
155+
crossinline writer: (CValuesRef<pw_encoder_t>?, T) -> Boolean
163156
): Boolean {
164-
val len = sizeOf(value)
165-
if (len == 0) return pw_encoder_write_bytes(raw, fieldNr, null, 0)
166-
val bytes = len * sizeBytes
167-
return value.usePinned { pinned ->
168-
pw_encoder_write_bytes(raw, fieldNr, ptr(pinned), bytes)
157+
val ktag = KTag(fieldNr, WireType.LENGTH_DELIMITED).toRawKTag()
158+
pw_encoder_write_tag(raw, ktag)
159+
// write the field size of the packed field
160+
val fieldSize = value.size * byteSize;
161+
pw_encoder_write_int32_no_tag(raw, fieldSize)
162+
for (v in value) {
163+
if (!writer(raw, v)) {
164+
return false
165+
}
169166
}
167+
return true
170168
}

grpc/grpc-core/src/nativeTest/kotlin/kotlinx/rpc/grpc/internal/WireCodecTest.kt

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -664,16 +664,14 @@ class WireCodecTest {
664664
assertTrue(buffer.exhausted())
665665
}
666666

667-
668-
private inline fun <A, T> runPackedTest(
669-
arr: A,
670-
crossinline write: WireEncoder.(Int, A) -> Boolean,
671-
crossinline read: WireDecoder.() -> List<T>?,
672-
crossinline asList: (A) -> List<T>
667+
private fun <T> runPackedTest(
668+
list: List<T>,
669+
write: WireEncoder.(Int, List<T>) -> Boolean,
670+
read: WireDecoder.() -> List<T>?,
673671
) {
674672
val buf = Buffer()
675673
with(WireEncoder(buf)) {
676-
assertTrue(write(1, arr))
674+
assertTrue(write(1, list))
677675
flush()
678676
}
679677
WireDecoder(buf).use { dec ->
@@ -682,56 +680,50 @@ class WireCodecTest {
682680
assertEquals(WireType.LENGTH_DELIMITED, wireType)
683681
}
684682
val test = dec.read()
685-
assertEquals(asList(arr), test)
683+
assertEquals(list, test)
686684
}
687685
assertTrue(buf.exhausted())
688686
}
689687

690688
@Test
691689
fun testPackedFixed32() = runPackedTest(
692-
UIntArray(1_000_000) { UInt.MAX_VALUE + it.toUInt() },
690+
List(1_000_000) { UInt.MAX_VALUE + it.toUInt() },
693691
WireEncoder::writePackedFixed32,
694-
WireDecoder::readPackedFixed32,
695-
UIntArray::asList
692+
WireDecoder::readPackedFixed32
696693
)
697694

698695
@Test
699696
fun testPackedFixed64() = runPackedTest(
700-
ULongArray(1_000_000) { UInt.MAX_VALUE + it.toULong() },
697+
List(1_000_000) { UInt.MAX_VALUE + it.toULong() },
701698
WireEncoder::writePackedFixed64,
702699
WireDecoder::readPackedFixed64,
703-
ULongArray::asList
704700
)
705701

706702
@Test
707703
fun testPackedSFixed32() = runPackedTest(
708-
IntArray(1_000_000) { Int.MAX_VALUE + it },
704+
List(1_000_000) { Int.MAX_VALUE + it },
709705
WireEncoder::writePackedSFixed32,
710-
WireDecoder::readPackedSFixed32,
711-
IntArray::asList
706+
WireDecoder::readPackedSFixed32
712707
)
713708

714709
@Test
715710
fun testPackedSFixed64() = runPackedTest(
716-
LongArray(1_000_000) { Long.MAX_VALUE + it },
711+
List(1_000_000) { Long.MAX_VALUE + it },
717712
WireEncoder::writePackedSFixed64,
718-
WireDecoder::readPackedSFixed64,
719-
LongArray::asList
713+
WireDecoder::readPackedSFixed64
720714
)
721715

722716
@Test
723717
fun testPackedFloat() = runPackedTest(
724-
FloatArray(1_000_000) { it.toFloat() / 3.3f * ((it and 1) * 2 - 1) },
718+
List(1_000_000) { it.toFloat() / 3.3f * ((it and 1) * 2 - 1) },
725719
WireEncoder::writePackedFloat,
726720
WireDecoder::readPackedFloat,
727-
FloatArray::asList
728721
)
729722

730723
@Test
731724
fun testPackedDouble() = runPackedTest(
732-
DoubleArray(1_000_000) { it.toDouble() / 3.3 * ((it and 1) * 2 - 1) },
725+
List(1_000_000) { it.toDouble() / 3.3 * ((it and 1) * 2 - 1) },
733726
WireEncoder::writePackedDouble,
734727
WireDecoder::readPackedDouble,
735-
DoubleArray::asList
736728
)
737729
}

grpc/grpcpp-c/include/protowire.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ extern "C" {
5151
bool pw_encoder_write_string(pw_encoder_t *self, int field_no, const char *data, int size);
5252
bool pw_encoder_write_bytes(pw_encoder_t *self, int field_no, const void *data, int size);
5353

54+
// No tag writers
55+
bool pw_encoder_write_tag(pw_encoder_t *self, uint32_t tag);
56+
bool pw_encoder_write_bool_no_tag(pw_encoder_t *self, bool value);
57+
bool pw_encoder_write_int32_no_tag(pw_encoder_t *self, int32_t value);
58+
bool pw_encoder_write_int64_no_tag(pw_encoder_t *self, int64_t value);
59+
bool pw_encoder_write_uint32_no_tag(pw_encoder_t *self, uint32_t value);
60+
bool pw_encoder_write_uint64_no_tag(pw_encoder_t *self, uint64_t value);
61+
bool pw_encoder_write_sint32_no_tag(pw_encoder_t *self, int32_t value);
62+
bool pw_encoder_write_sint64_no_tag(pw_encoder_t *self, int64_t value);
63+
bool pw_encoder_write_fixed32_no_tag(pw_encoder_t *self, uint32_t value);
64+
bool pw_encoder_write_fixed64_no_tag(pw_encoder_t *self, uint64_t value);
65+
bool pw_encoder_write_sfixed32_no_tag(pw_encoder_t *self, int32_t value);
66+
bool pw_encoder_write_sfixed64_no_tag(pw_encoder_t *self, int64_t value);
67+
bool pw_encoder_write_float_no_tag(pw_encoder_t *self, float value);
68+
bool pw_encoder_write_double_no_tag(pw_encoder_t *self, double value);
69+
5470

5571
//// WIRE DECODER ////
5672

@@ -78,6 +94,7 @@ extern "C" {
7894
*/
7995
pw_decoder_t * pw_decoder_new(pw_zero_copy_input_t zero_copy_input);
8096
void pw_decoder_delete(pw_decoder_t *self);
97+
void pw_decoder_close(pw_decoder_t *self);
8198

8299
uint32_t pw_decoder_read_tag(pw_decoder_t *self);
83100
bool pw_decoder_read_bool(pw_decoder_t *self, bool *value);

grpc/grpcpp-c/src/protowire.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,35 @@ extern "C" {
180180
return check(self);
181181
}
182182

183+
bool pw_encoder_write_tag(pw_encoder_t *self, uint32_t tag) {
184+
self->cos.WriteTag(tag);
185+
return check(self);
186+
}
187+
188+
#define WRITE_FIELD_NO_TAG( funcSuffix, wireTy, cTy) \
189+
bool pw_encoder_write_##funcSuffix##_no_tag(pw_encoder_t *self, cTy value) { \
190+
WireFormatLite::Write##wireTy##NoTag(value, &self->cos); \
191+
return check(self); \
192+
}
193+
194+
WRITE_FIELD_NO_TAG( bool, Bool, bool)
195+
WRITE_FIELD_NO_TAG( int32, Int32, int32_t)
196+
WRITE_FIELD_NO_TAG( int64, Int64, int64_t)
197+
WRITE_FIELD_NO_TAG( uint32, UInt32, uint32_t)
198+
WRITE_FIELD_NO_TAG( uint64, UInt64, uint64_t)
199+
WRITE_FIELD_NO_TAG( sint32, SInt32, int32_t)
200+
WRITE_FIELD_NO_TAG( sint64, SInt64, int64_t)
201+
WRITE_FIELD_NO_TAG( fixed32, Fixed32, uint32_t)
202+
WRITE_FIELD_NO_TAG( fixed64, Fixed64, uint64_t)
203+
WRITE_FIELD_NO_TAG( sfixed32, SFixed32, int32_t)
204+
WRITE_FIELD_NO_TAG( sfixed64, SFixed64, int64_t)
205+
WRITE_FIELD_NO_TAG( float, Float, float)
206+
WRITE_FIELD_NO_TAG( double, Double, double)
207+
WRITE_FIELD_NO_TAG( enum, Enum, int)
208+
209+
210+
/// DECODER IMPLEMENATION ///
211+
183212
pw_decoder_t *pw_decoder_new(pw_zero_copy_input_t zero_copy_input) {
184213
return new pw_decoder_t(zero_copy_input);
185214
}
@@ -188,6 +217,11 @@ extern "C" {
188217
delete self;
189218
}
190219

220+
void pw_decoder_close(pw_decoder_t *self) {
221+
// the deconstructor backs the stream up to the current position.
222+
self->cis.~CodedInputStream();
223+
}
224+
191225
uint32_t pw_decoder_read_tag(pw_decoder_t *self) {
192226
return self->cis.ReadTag();
193227
}

0 commit comments

Comments
 (0)