8
8
9
9
namespace ProtoBuf . Logic
10
10
{
11
+ internal class BindingContext
12
+ {
13
+ public ConcurrentDictionary < ( Type_Context , string names ) , ParserRuleContext ? > TypeBindingCache { get ; } = new ( ) ;
14
+ public ConcurrentDictionary < ( MessageDefContext ? messageDef , int fieldIndex ) , FieldContext ? > FieldCache { get ; } = new ( ) ;
15
+ }
16
+
11
17
internal class MessageBinder : IMessage
12
18
{
13
19
enum FieldType
@@ -17,16 +23,14 @@ enum FieldType
17
23
Packed
18
24
}
19
25
20
- public MessageBinder ( ProtoContext protoContext , MessageDefContext ? messageDef ) : this ( protoContext , messageDef , null ) { }
21
-
22
- private MessageBinder ( ProtoContext protoContext , MessageDefContext ? messageDef , ConcurrentDictionary < ( Type_Context , string names ) , ParserRuleContext ? > ? cache )
26
+ public MessageBinder ( ProtoContext protoContext , MessageDefContext ? messageDef , BindingContext bindingContext )
23
27
{
24
28
ProtoContext = protoContext ;
25
29
MessageDef = messageDef ;
26
- BindingCache = cache ?? new ( ) ;
30
+ BindingContext = bindingContext ?? new ( ) ;
27
31
}
28
32
29
- private ConcurrentDictionary < ( Type_Context , string names ) , ParserRuleContext ? > BindingCache { get ; }
33
+ private BindingContext BindingContext { get ; }
30
34
public ProtoContext ProtoContext { get ; }
31
35
public MessageDefContext ? MessageDef { get ; }
32
36
public TypedMessage ? Result { get ; private set ; }
@@ -39,7 +43,8 @@ public void MergeFrom(CodedInputStream input)
39
43
while ( input . Position < targetPosition && ! input . IsAtEnd )
40
44
{
41
45
var ( index , type ) = input . ReadWireTag ( ) ;
42
- var field = MessageDef ? . messageBody ( ) . messageElement ( ) . Select ( x => x . field ( ) ) . FirstOrDefault ( x => int . TryParse ( x ? . fieldNumber ( ) ? . GetText ( ) , out var i ) && i == index ) ;
46
+ var field = BindingContext . FieldCache . GetOrAdd ( ( MessageDef , index ) ,
47
+ key => key . messageDef ? . messageBody ( ) . messageElement ( ) . Select ( x => x . field ( ) ) . FirstOrDefault ( x => int . TryParse ( x ? . fieldNumber ( ) ? . GetText ( ) , out var i ) && i == key . fieldIndex ) ) ;
43
48
var parsedFields = MessageDef != null && field != null && FitsFieldType ( type , field . type_ ( ) ) is var fieldType and not FieldType . Unknown
44
49
? ParseField ( input , fieldType , field )
45
50
: ParseUnknownField ( input , new WireTag ( index , type ) ) ;
@@ -184,15 +189,15 @@ static IEnumerable<string> DottedNames(EnumTypeContext message)
184
189
{
185
190
var namesString = string . Join ( "." , names ) ;
186
191
var key = ( expectedType , namesString ) ;
187
- if ( BindingCache . TryGetValue ( key , out var cached ) )
192
+ if ( BindingContext . TypeBindingCache . TryGetValue ( key , out var cached ) )
188
193
{
189
194
return cached ;
190
195
}
191
196
else
192
197
{
193
198
var result = BindType ( names , expectedType , names => new MessageDefBinder ( names ) ) as ParserRuleContext
194
199
?? BindType ( names , expectedType , names => new EnumDefBinder ( names ) ) ;
195
- BindingCache . TryAdd ( key , result ) ;
200
+ BindingContext . TypeBindingCache . TryAdd ( key , result ) ;
196
201
return result ;
197
202
}
198
203
}
@@ -211,7 +216,7 @@ static IEnumerable<string> DottedNames(EnumTypeContext message)
211
216
212
217
private ProtoType ? ParseMessage ( CodedInputStream stream , MessageDefContext ? messageDef )
213
218
{
214
- var builder = new MessageBinder ( ProtoContext , messageDef , BindingCache ) ;
219
+ var builder = new MessageBinder ( ProtoContext , messageDef , BindingContext ) ;
215
220
stream . ReadRawMessage ( builder ) ;
216
221
return builder . Result ;
217
222
}
0 commit comments