1919package com.google.firebase.dataconnect.util
2020
2121import com.google.firebase.dataconnect.AnyValue
22+ import com.google.firebase.dataconnect.DataConnectPath
2223import com.google.firebase.dataconnect.serializers.AnyValueSerializer
24+ import com.google.firebase.dataconnect.toPathString
2325import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeBoolean
2426import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeByte
2527import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeChar
@@ -34,6 +36,8 @@ import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeShort
3436import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeString
3537import com.google.firebase.dataconnect.util.ProtoDecoderUtil.decodeStruct
3638import com.google.firebase.dataconnect.util.ProtoUtil.toAny
39+ import com.google.firebase.dataconnect.withAddedField
40+ import com.google.firebase.dataconnect.withAddedListIndex
3741import com.google.protobuf.ListValue
3842import com.google.protobuf.NullValue
3943import com.google.protobuf.Struct
@@ -58,59 +62,64 @@ import kotlinx.serialization.modules.SerializersModule
5862 * avoids this public API pollution.
5963 */
6064private object ProtoDecoderUtil {
61- fun <T > decode (value : Value , path : String? , expectedKindCase : KindCase , block : (Value ) -> T ): T =
65+ fun <T > decode (
66+ value : Value ,
67+ path : DataConnectPath ,
68+ expectedKindCase : KindCase ,
69+ block : (Value ) -> T
70+ ): T =
6271 if (value.kindCase != expectedKindCase) {
6372 throw SerializationException (
64- (if (path == = null ) " " else " decoding \" $path \" failed: " ) +
73+ (if (path.isEmpty()) " " else " decoding \" ${ path.toPathString()} \" failed: " ) +
6574 " expected $expectedKindCase , but got ${value.kindCase} (${value.toAny()} )"
6675 )
6776 } else {
6877 block(value)
6978 }
7079
71- fun decodeBoolean (value : Value , path : String? ): Boolean =
80+ fun decodeBoolean (value : Value , path : DataConnectPath ): Boolean =
7281 decode(value, path, KindCase .BOOL_VALUE ) { it.boolValue }
7382
74- fun decodeByte (value : Value , path : String? ): Byte =
83+ fun decodeByte (value : Value , path : DataConnectPath ): Byte =
7584 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue.toInt().toByte() }
7685
77- fun decodeChar (value : Value , path : String? ): Char =
86+ fun decodeChar (value : Value , path : DataConnectPath ): Char =
7887 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue.toInt().toChar() }
7988
80- fun decodeDouble (value : Value , path : String? ): Double =
89+ fun decodeDouble (value : Value , path : DataConnectPath ): Double =
8190 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue }
8291
83- fun decodeEnum (value : Value , path : String? ): String =
92+ fun decodeEnum (value : Value , path : DataConnectPath ): String =
8493 decode(value, path, KindCase .STRING_VALUE ) { it.stringValue }
8594
86- fun decodeFloat (value : Value , path : String? ): Float =
95+ fun decodeFloat (value : Value , path : DataConnectPath ): Float =
8796 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue.toFloat() }
8897
89- fun decodeString (value : Value , path : String? ): String =
98+ fun decodeString (value : Value , path : DataConnectPath ): String =
9099 decode(value, path, KindCase .STRING_VALUE ) { it.stringValue }
91100
92- fun decodeStruct (value : Value , path : String? ): Struct =
101+ fun decodeStruct (value : Value , path : DataConnectPath ): Struct =
93102 decode(value, path, KindCase .STRUCT_VALUE ) { it.structValue }
94103
95- fun decodeList (value : Value , path : String? ): ListValue =
104+ fun decodeList (value : Value , path : DataConnectPath ): ListValue =
96105 decode(value, path, KindCase .LIST_VALUE ) { it.listValue }
97106
98- fun decodeNull (value : Value , path : String? ): NullValue =
107+ fun decodeNull (value : Value , path : DataConnectPath ): NullValue =
99108 decode(value, path, KindCase .NULL_VALUE ) { it.nullValue }
100109
101- fun decodeInt (value : Value , path : String? ): Int =
110+ fun decodeInt (value : Value , path : DataConnectPath ): Int =
102111 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue.toInt() }
103112
104- fun decodeLong (value : Value , path : String? ): Long =
113+ fun decodeLong (value : Value , path : DataConnectPath ): Long =
105114 decode(value, path, KindCase .STRING_VALUE ) { it.stringValue.toLong() }
106115
107- fun decodeShort (value : Value , path : String? ): Short =
116+ fun decodeShort (value : Value , path : DataConnectPath ): Short =
108117 decode(value, path, KindCase .NUMBER_VALUE ) { it.numberValue.toInt().toShort() }
109118}
110119
111120internal class ProtoValueDecoder (
112121 internal val valueProto : Value ,
113- private val path : String? ,
122+ private val path : DataConnectPath ,
114123 override val serializersModule : SerializersModule
115124) : Decoder {
116125
@@ -162,7 +171,7 @@ internal class ProtoValueDecoder(
162171
163172private class ProtoStructValueDecoder (
164173 private val struct : Struct ,
165- private val path : String? ,
174+ private val path : DataConnectPath ,
166175 override val serializersModule : SerializersModule
167176) : CompositeDecoder {
168177
@@ -228,7 +237,7 @@ private class ProtoStructValueDecoder(
228237 private fun <T > decodeValueElement (
229238 descriptor : SerialDescriptor ,
230239 index : Int ,
231- block : (Value , String? ) -> T
240+ block : (Value , DataConnectPath ) -> T
232241 ): T {
233242 val elementName = descriptor.getElementName(index)
234243 val elementPath = elementPathForName(elementName)
@@ -290,13 +299,13 @@ private class ProtoStructValueDecoder(
290299 }
291300 }
292301
293- private fun elementPathForName (elementName : String ) =
294- if ( path == = null ) elementName else " ${path} . ${ elementName} "
302+ private fun elementPathForName (elementName : String ): DataConnectPath =
303+ path.withAddedField( elementName)
295304}
296305
297306private class ProtoListValueDecoder (
298307 private val list : ListValue ,
299- private val path : String? ,
308+ private val path : DataConnectPath ,
300309 override val serializersModule : SerializersModule
301310) : CompositeDecoder {
302311
@@ -339,7 +348,7 @@ private class ProtoListValueDecoder(
339348 override fun decodeStringElement (descriptor : SerialDescriptor , index : Int ) =
340349 decodeValueElement(index, ProtoDecoderUtil ::decodeString)
341350
342- private inline fun <T > decodeValueElement (index : Int , block : (Value , String? ) -> T ): T =
351+ private inline fun <T > decodeValueElement (index : Int , block : (Value , DataConnectPath ) -> T ): T =
343352 block(list.valuesList[index], elementPathForIndex(index))
344353
345354 override fun <T > decodeSerializableElement (
@@ -373,14 +382,15 @@ private class ProtoListValueDecoder(
373382 decodeSerializableElement(descriptor, index, deserializer, previousValue = null )
374383 }
375384
376- private fun elementPathForIndex (index : Int ) = if (path == = null ) " [ $index ] " else " ${ path} [ $ index] "
385+ private fun elementPathForIndex (index : Int ): DataConnectPath = path.withAddedListIndex( index)
377386
378- override fun toString () = " ProtoListValueDecoder{path=$path , size=${list.valuesList.size} "
387+ override fun toString () =
388+ " ProtoListValueDecoder{path=${path.toPathString()} , size=${list.valuesList.size} }"
379389}
380390
381391private class ProtoMapValueDecoder (
382392 private val struct : Struct ,
383- private val path : String? ,
393+ private val path : DataConnectPath ,
384394 override val serializersModule : SerializersModule
385395) : CompositeDecoder {
386396
@@ -435,7 +445,7 @@ private class ProtoMapValueDecoder(
435445 decodeValueElement(index, ProtoDecoderUtil ::decodeString)
436446 }
437447
438- private inline fun <T > decodeValueElement (index : Int , block : (Value , String? ) -> T ): T {
448+ private inline fun <T > decodeValueElement (index : Int , block : (Value , DataConnectPath ) -> T ): T {
439449 require(index % 2 != 0 ) { " invalid value index: $index " }
440450 val value = structEntryByElementIndex(index).value
441451 val elementPath = elementPathForIndex(index)
@@ -491,21 +501,22 @@ private class ProtoMapValueDecoder(
491501 return deserializer.deserialize(elementDecoder)
492502 }
493503
494- private fun elementPathForIndex (index : Int ): String {
504+ private fun elementPathForIndex (index : Int ): DataConnectPath {
495505 val structEntry = structEntryByElementIndex(index)
496506 val key = structEntry.key
497507 return if (index % 2 == 0 ) {
498- if ( path == = null ) " [ $ key] " else " ${path} [ $key ] "
508+ path.withAddedField( key)
499509 } else {
500- if ( path == = null ) " [ $key ].value " else " ${path} [ $ key]. value"
510+ path.withAddedField( key).withAddedField( " value" )
501511 }
502512 }
503513
504- override fun toString () = " ProtoMapValueDecoder{path=$path , size=${struct.fieldsCount} "
514+ override fun toString () =
515+ " ProtoMapValueDecoder{path=${path.toPathString()} , size=${struct.fieldsCount} "
505516}
506517
507518private class ProtoObjectValueDecoder (
508- val path : String? ,
519+ val path : DataConnectPath ,
509520 override val serializersModule : SerializersModule
510521) : CompositeDecoder {
511522
@@ -553,12 +564,12 @@ private class ProtoObjectValueDecoder(
553564
554565 override fun endStructure (descriptor : SerialDescriptor ) {}
555566
556- override fun toString () = " ProtoObjectValueDecoder{path=$path }"
567+ override fun toString () = " ProtoObjectValueDecoder{path=${ path.toPathString()} }"
557568}
558569
559570private class MapKeyDecoder (
560571 val key : String ,
561- val path : String ,
572+ val path : DataConnectPath ,
562573 override val serializersModule : SerializersModule
563574) : Decoder {
564575
@@ -595,5 +606,5 @@ private class MapKeyDecoder(
595606 " The only valid method call on MapKeyDecoder is decodeString()"
596607 )
597608
598- override fun toString () = " MapKeyDecoder{path=$path }"
609+ override fun toString () = " MapKeyDecoder{path=${ path.toPathString()} }"
599610}
0 commit comments