Skip to content

Commit

Permalink
✨ Add copyFrom and fillFrom method for MutableMessage (#62)
Browse files Browse the repository at this point in the history
* Add copyFrom and fillFrom method for MutableMessage

* Change method name

Co-authored-by: Kanro <[email protected]>
  • Loading branch information
yuxin-zhao and devkanro authored Aug 27, 2020
1 parent f6da309 commit 3581332
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,23 @@ abstract class AbstractMessage<T : Message<T, TM>, TM : MutableMessage<T, TM>>(
}

override fun fieldDescriptor(fieldName: String): FieldDescriptorProto {
return _support.fieldInfo(fieldName)
?: _extensions.values.firstNotNull { it.fieldInfo(fieldName) }
return fieldDescriptorOrNull(fieldName)
?: throw IllegalArgumentException("Message not contains field definition of '$fieldName'.")
}

override fun fieldDescriptor(fieldNumber: Int): FieldDescriptorProto {
return fieldDescriptorOrNull(fieldNumber)
?: throw IllegalArgumentException("Message not contains field definition of '$fieldNumber'.")
}

override fun fieldDescriptorOrNull(fieldName: String): FieldDescriptorProto? {
return _support.fieldInfo(fieldName)
?: _extensions.values.firstNotNull { it.fieldInfo(fieldName) }
}

override fun fieldDescriptorOrNull(fieldNumber: Int): FieldDescriptorProto? {
return _support.fieldInfo(fieldNumber)
?: _extensions.values.firstNotNull { it.fieldInfo(fieldNumber) }
?: throw IllegalArgumentException("Message not contains field definition of '$fieldNumber'.")
}

fun invalidCache() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
package com.bybutter.sisyphus.protobuf

import com.bybutter.sisyphus.protobuf.primitives.BoolValue
import com.bybutter.sisyphus.protobuf.primitives.BytesValue
import com.bybutter.sisyphus.protobuf.primitives.DoubleValue
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.BOOL
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.BYTES
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.DOUBLE
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.FLOAT
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.INT32
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.INT64
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.MESSAGE
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.STRING
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.UINT32
import com.bybutter.sisyphus.protobuf.primitives.FieldDescriptorProto.Type.UINT64
import com.bybutter.sisyphus.protobuf.primitives.FloatValue
import com.bybutter.sisyphus.protobuf.primitives.Int32Value
import com.bybutter.sisyphus.protobuf.primitives.Int64Value
import com.bybutter.sisyphus.protobuf.primitives.StringValue
import com.bybutter.sisyphus.protobuf.primitives.UInt32Value
import com.bybutter.sisyphus.protobuf.primitives.UInt64Value
import com.google.protobuf.CodedInputStream
import com.google.protobuf.WireFormat

Expand Down Expand Up @@ -28,6 +48,14 @@ abstract class AbstractMutableMessage<T : Message<T, TM>, TM : MutableMessage<T,
}
}

override fun copyFrom(message: Message<*, *>) {
copyFrom(message, false)
}

override fun fillFrom(message: Message<*, *>) {
copyFrom(message, true)
}

override fun <T> set(fieldName: String, value: T) {
if (!fieldName.contains('.')) {
return setFieldInCurrent(fieldName, value)
Expand Down Expand Up @@ -109,4 +137,54 @@ abstract class AbstractMutableMessage<T : Message<T, TM>, TM : MutableMessage<T,
extension.clear()
}
}

private fun copyFrom(message: Message<*, *>, keepOriginalValues: Boolean = false) {
for (source in message.descriptor().field) {
val target = this.fieldDescriptorOrNull(source.name) ?: continue

if (keepOriginalValues && this.has(source.name)) continue

if (target.type == source.type && target.typeName == source.typeName) {
if (target.label == source.label) {
this[target.name] = message.get<Any>(source.name)
continue
}
if (target.label == FieldDescriptorProto.Label.REPEATED) {
this[target.name] = listOf(message.get<Any>(source.name))
continue
}
}

if (target.type == MESSAGE && target.typeName == WellKnownTypes.ANY_TYPENAME) {
if (target.label == FieldDescriptorProto.Label.REPEATED) {
this[target.name] = if (source.label == FieldDescriptorProto.Label.REPEATED) {
message.get<List<Any>>(source.name).mapNotNull {
buildTypeMessage(source.type, it)
}
} else {
listOf(buildTypeMessage(source.type, message[source.name]) ?: continue)
}
continue
}
if (source.label != FieldDescriptorProto.Label.REPEATED) {
this[target.name] = buildTypeMessage(source.type, message[source.name]) ?: continue
}
}
}
}

private fun buildTypeMessage(type: FieldDescriptorProto.Type, value: Any): Message<*, *>? {
return when (type) {
DOUBLE -> DoubleValue { this.value = value as Double }
FLOAT -> FloatValue { this.value = value as Float }
INT64 -> Int64Value { this.value = value as Long }
UINT64 -> UInt64Value { this.value = value as ULong }
INT32 -> Int32Value { this.value = value as Int }
BOOL -> BoolValue { this.value = value as Boolean }
STRING -> StringValue { this.value = value as String }
BYTES -> BytesValue { this.value = value as ByteArray }
UINT32 -> UInt32Value { this.value = value as UInt }
else -> null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ interface Message<T : Message<T, TM>, TM : MutableMessage<T, TM>> : Cloneable {

fun fieldDescriptors(): List<FieldDescriptorProto>

fun fieldDescriptorOrNull(fieldName: String): FieldDescriptorProto?

fun fieldDescriptorOrNull(fieldNumber: Int): FieldDescriptorProto?

fun fieldDescriptor(fieldName: String): FieldDescriptorProto

fun fieldDescriptor(fieldNumber: Int): FieldDescriptorProto
Expand Down Expand Up @@ -123,14 +127,28 @@ interface MutableMessage<T : Message<T, TM>, TM : MutableMessage<T, TM>> : Messa
fun clear(fieldNumber: Int): Any?

/**
* Clear all optional and repeated fields
* Clear all optional and repeated fields.
*/
fun clear()

/**
* Merge another message to current mutable message
* Merge another message to current mutable message.
*/
fun mergeWith(other: T?)

/**
* Copy another message to current mutable message.
*
* Will overwrite current mutable message value.
* */
fun copyFrom(message: Message<*, *>)

/**
* Fill another message to current mutable message.
*
* Keep current mutable message value.
* */
fun fillFrom(message: Message<*, *>)

fun readFrom(input: CodedInputStream, size: Int)
}

0 comments on commit 3581332

Please sign in to comment.