@@ -9,33 +9,62 @@ import kotlinx.serialization.protobuf.internal.*
99import kotlinx.serialization.protobuf.internal.ProtoWireType
1010
1111/* *
12- * Mark a property as a holder for unknown fields in protobuf message.
12+ * Mark a property with type [ProtoMessage] as a holder for unknown fields in protobuf message.
13+ *
14+ * All the contents with unregistered proto number will be stored in this field.
1315 */
1416@SerialInfo
1517@Target(AnnotationTarget .PROPERTY )
1618@ExperimentalSerializationApi
1719public annotation class ProtoUnknownFields
1820
21+ /* *
22+ * Represents a protobuf message.
23+ *
24+ * Especially used as a holder of unknown proto fields in an arbitrary protobuf message.
25+ */
1926@Serializable(with = ProtoMessageSerializer ::class )
2027public class ProtoMessage internal constructor(
21- public val fields : List <ProtoField >
28+ internal val fields : List <ProtoField >
2229) {
2330 public companion object {
31+ /* *
32+ * An empty [ProtoMessage] instance.
33+ *
34+ * Useful as a default value for [ProtoUnknownFields] properties.
35+ */
2436 public val Empty : ProtoMessage = ProtoMessage (emptyList())
2537 }
2638
39+ /* *
40+ * Number of fields holding in the message.
41+ */
2742 public val size: Int get() = fields.size
28- public fun asByteArray (): ByteArray = fields.fold(ByteArray (0 )) { acc, protoField -> acc + protoField.asWireContent() }
2943
30- public constructor (vararg fields: ProtoField ) : this (fields.toList())
44+ /* *
45+ * Returns a byte array representing of the message.
46+ */
47+ public fun asByteArray (): ByteArray =
48+ fields.fold(ByteArray (0 )) { acc, protoField -> acc + protoField.asWireContent() }
49+
50+ internal constructor (vararg fields: ProtoField ) : this (fields.toList())
3151
52+ /* *
53+ * Merges two [ProtoMessage] instances.
54+ */
3255 public operator fun plus (other : ProtoMessage ): ProtoMessage = merge(other)
3356
57+ /* *
58+ * Merges two [ProtoMessage] instances.
59+ */
3460 public fun merge (other : ProtoMessage ): ProtoMessage {
3561 return ProtoMessage (fields + other.fields)
3662 }
3763
38- public fun merge (vararg field : ProtoField ): ProtoMessage {
64+ /* *
65+ * Convenience method to merge multiple [ProtoField] with this message.
66+ */
67+ internal fun merge (vararg field : ProtoField ): ProtoMessage {
3968 return ProtoMessage (fields + field)
4069 }
4170
@@ -53,6 +82,9 @@ public class ProtoMessage internal constructor(
5382 }
5483}
5584
85+ /* *
86+ * Convenience method to merge two nullable [ProtoMessage] instances.
87+ */
5688public fun ProtoMessage?.merge (other : ProtoMessage ? ): ProtoMessage {
5789 return when {
5890 this == null -> other ? : ProtoMessage .Empty
@@ -61,29 +93,35 @@ public fun ProtoMessage?.merge(other: ProtoMessage?): ProtoMessage {
6193 }
6294}
6395
64- public fun ProtoMessage?.merge (vararg fields : ProtoField ): ProtoMessage {
96+ /* *
97+ * Convenience method to merge multiple [ProtoField] with a nullable [ProtoMessage].
98+ */
99+ internal fun ProtoMessage?.merge (vararg fields : ProtoField ): ProtoMessage {
65100 return when {
66101 this == null -> ProtoMessage (fields.toList())
67102 else -> this .merge(ProtoMessage (fields.toList()))
68103 }
69104}
70105
106+ /* *
107+ * Represents a single field in a protobuf message.
108+ */
71109@OptIn(ExperimentalSerializationApi ::class )
72110@Serializable(with = ProtoFieldSerializer ::class )
73111@KeepGeneratedSerializer
74112@ConsistentCopyVisibility
75- public data class ProtoField internal constructor(
113+ internal data class ProtoField internal constructor(
76114 internal val id : Int ,
77115 internal val wireType : ProtoWireType ,
78116 internal val data : ProtoContentHolder
79117) {
80- public companion object {
81- public val Empty : ProtoField = ProtoField (0 , ProtoWireType .INVALID , ProtoContentHolder .ByteArrayContent (ByteArray (0 )))
118+ companion object {
119+ val Empty : ProtoField = ProtoField (0 , ProtoWireType .INVALID , ProtoContentHolder .ByteArrayContent (ByteArray (0 )))
82120 }
83121
84- public fun asWireContent (): ByteArray = byteArrayOf(((id shl 3 ) or wireType.typeId).toByte()) + data.byteArray
122+ fun asWireContent (): ByteArray = byteArrayOf(((id shl 3 ) or wireType.typeId).toByte()) + data.byteArray
85123
86- public val contentLength: Int
124+ val contentLength: Int
87125 get() = asWireContent().size
88126
89127 override fun equals (other : Any? ): Boolean {
@@ -107,9 +145,19 @@ public data class ProtoField internal constructor(
107145 }
108146}
109147
148+ /* *
149+ * A data representation of a protobuf field in [ProtoField.data], without the field number and wire type.
150+ */
110151internal sealed interface ProtoContentHolder {
152+
153+ /* *
154+ * Returns a byte array representation of the content.
155+ */
111156 val byteArray: ByteArray
112157
158+ /* *
159+ * Represents the content in raw byte array.
160+ */
113161 data class ByteArrayContent (override val byteArray : ByteArray ) : ProtoContentHolder {
114162 override fun equals (other : Any? ): Boolean {
115163 return other is ProtoContentHolder && this .contentEquals(other)
@@ -120,6 +168,9 @@ internal sealed interface ProtoContentHolder {
120168 }
121169 }
122170
171+ /* *
172+ * Represents the content with a nested [ProtoMessage].
173+ */
123174 data class MessageContent (val content : ProtoMessage ) : ProtoContentHolder {
124175 override val byteArray: ByteArray
125176 get() = content.asByteArray()
@@ -134,15 +185,27 @@ internal sealed interface ProtoContentHolder {
134185 }
135186}
136187
188+ /* *
189+ * Creates a [ProtoContentHolder] instance with a byte array content.
190+ */
137191internal fun ProtoContentHolder (content : ByteArray ): ProtoContentHolder = ProtoContentHolder .ByteArrayContent (content)
138192
193+ /* *
194+ * Get the length in bytes of the content in the [ProtoContentHolder].
195+ */
139196internal val ProtoContentHolder .contentLength: Int
140197 get() = byteArray.size
141198
199+ /* *
200+ * Checks if the content of two [ProtoContentHolder] instances are equal.
201+ */
142202internal fun ProtoContentHolder.contentEquals (other : ProtoContentHolder ): Boolean {
143203 return byteArray.contentEquals(other.byteArray)
144204}
145205
206+ /* *
207+ * Calculates the hash code of the content in the [ProtoContentHolder].
208+ */
146209internal fun ProtoContentHolder.contentHashCode (): Int {
147210 return byteArray.contentHashCode()
148211}
0 commit comments