@@ -41,6 +41,11 @@ func NewDefiner(opts ...Option) *Definer {
41
41
// BuildTarget seeks the target message in the given protobuf snippet and
42
42
// returns a proto.Message that can be used to respond requests or match requests to.
43
43
func (b * Definer ) BuildTarget (def string ) (proto.Message , error ) {
44
+ def , err := b .joinMultilineStrings (def )
45
+ if err != nil {
46
+ return nil , fmt .Errorf ("invalid file: %w" , err )
47
+ }
48
+
44
49
def = b .enrich (def )
45
50
46
51
fd , err := b .parseDefinition (def )
@@ -61,6 +66,59 @@ func (b *Definer) BuildTarget(def string) (proto.Message, error) {
61
66
return protoadapt .MessageV2Of (msg ), nil
62
67
}
63
68
69
+ // joinMultilineStrings replaces the multiline strings enclosed in "`" symbol into
70
+ // a single line string, enclosed in double quotes, with escaped newlines, tabs,
71
+ // and double quotes.
72
+ func (b * Definer ) joinMultilineStrings (def string ) (string , error ) {
73
+ var sb strings.Builder
74
+
75
+ type pos struct { Line , Col int }
76
+ curr , backtickStart := pos {Line : 1 }, pos {}
77
+
78
+ countPos := func (r rune ) {
79
+ if r != '\n' {
80
+ curr .Col ++
81
+ return
82
+ }
83
+
84
+ curr .Line ++
85
+ curr .Col = 0
86
+ }
87
+
88
+ inMultiline := false
89
+ for _ , r := range def {
90
+ countPos (r )
91
+
92
+ switch {
93
+ case r == '`' :
94
+ if ! inMultiline {
95
+ backtickStart = curr
96
+ }
97
+ inMultiline = ! inMultiline
98
+ _ , _ = sb .WriteRune ('"' )
99
+ case inMultiline :
100
+ switch r {
101
+ case '\n' :
102
+ _ , _ = sb .WriteString (`\n` )
103
+ case '\t' :
104
+ _ , _ = sb .WriteString (`\t` )
105
+ case '"' :
106
+ _ , _ = sb .WriteString (`\"` )
107
+ default :
108
+ _ , _ = sb .WriteRune (r )
109
+ }
110
+ default :
111
+ _ , _ = sb .WriteRune (r )
112
+ }
113
+ }
114
+
115
+ if inMultiline {
116
+ return "" , errUnclosedMultilineString (backtickStart )
117
+ }
118
+
119
+ return sb .String (), nil
120
+ }
121
+
64
122
func (b * Definer ) enrich (def string ) string {
65
123
sb := & strings.Builder {}
66
124
_ , _ = fmt .Fprintln (sb , `syntax = "proto3";` )
@@ -335,7 +393,20 @@ var types = map[descriptorpb.FieldDescriptorProto_Type]any{
335
393
descriptorpb .FieldDescriptorProto_TYPE_SINT64 : int64 (0 ),
336
394
}
337
395
396
+ func floatparser (_ fieldDescriptor , s string ) (any , error ) {
397
+ return strconv .ParseFloat (s , 64 )
398
+ }
399
+
400
+ func intparser (_ fieldDescriptor , s string ) (any , error ) {
401
+ return strconv .ParseInt (s , 10 , 64 )
402
+ }
403
+
404
+ func uintparser (_ fieldDescriptor , s string ) (any , error ) {
405
+ return strconv .ParseUint (s , 10 , 64 )
406
+ }
407
+
338
408
var parsers = map [descriptorpb.FieldDescriptorProto_Type ]func (fd fieldDescriptor , s string ) (any , error ){
409
+ descriptorpb .FieldDescriptorProto_TYPE_STRING : func (_ fieldDescriptor , s string ) (any , error ) { return s , nil },
339
410
descriptorpb .FieldDescriptorProto_TYPE_MESSAGE : func (fd fieldDescriptor , s string ) (any , error ) {
340
411
msg := dynamic .NewMessage (fd .GetMessageType ())
341
412
if err := msg .UnmarshalJSON ([]byte (s )); err != nil {
@@ -351,24 +422,28 @@ var parsers = map[descriptorpb.FieldDescriptorProto_Type]func(fd fieldDescriptor
351
422
return nil , fmt .Errorf ("unknown enum value: %s" , s )
352
423
},
353
424
354
- descriptorpb .FieldDescriptorProto_TYPE_STRING : func (_ fieldDescriptor , s string ) (any , error ) { return s , nil },
355
- descriptorpb .FieldDescriptorProto_TYPE_BYTES : func (_ fieldDescriptor , s string ) (any , error ) { return base64 .StdEncoding .DecodeString (s ) },
356
- descriptorpb .FieldDescriptorProto_TYPE_BOOL : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseBool (s ) },
357
-
358
- descriptorpb .FieldDescriptorProto_TYPE_DOUBLE : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseFloat (s , 64 ) },
359
- descriptorpb .FieldDescriptorProto_TYPE_FLOAT : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseFloat (s , 64 ) },
360
-
361
- descriptorpb .FieldDescriptorProto_TYPE_INT64 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
362
- descriptorpb .FieldDescriptorProto_TYPE_INT32 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
363
- descriptorpb .FieldDescriptorProto_TYPE_FIXED64 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
364
- descriptorpb .FieldDescriptorProto_TYPE_FIXED32 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
365
- descriptorpb .FieldDescriptorProto_TYPE_SFIXED32 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
366
- descriptorpb .FieldDescriptorProto_TYPE_SFIXED64 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
367
- descriptorpb .FieldDescriptorProto_TYPE_SINT32 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
368
- descriptorpb .FieldDescriptorProto_TYPE_SINT64 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseInt (s , 10 , 64 ) },
369
-
370
- descriptorpb .FieldDescriptorProto_TYPE_UINT32 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseUint (s , 10 , 64 ) },
371
- descriptorpb .FieldDescriptorProto_TYPE_UINT64 : func (_ fieldDescriptor , s string ) (any , error ) { return strconv .ParseUint (s , 10 , 64 ) },
425
+ descriptorpb .FieldDescriptorProto_TYPE_BYTES : func (_ fieldDescriptor , s string ) (any , error ) {
426
+ return base64 .StdEncoding .DecodeString (s )
427
+ },
428
+
429
+ descriptorpb .FieldDescriptorProto_TYPE_BOOL : func (_ fieldDescriptor , s string ) (any , error ) {
430
+ return strconv .ParseBool (s )
431
+ },
432
+
433
+ descriptorpb .FieldDescriptorProto_TYPE_DOUBLE : floatparser ,
434
+ descriptorpb .FieldDescriptorProto_TYPE_FLOAT : floatparser ,
435
+
436
+ descriptorpb .FieldDescriptorProto_TYPE_INT64 : intparser ,
437
+ descriptorpb .FieldDescriptorProto_TYPE_INT32 : intparser ,
438
+ descriptorpb .FieldDescriptorProto_TYPE_FIXED64 : intparser ,
439
+ descriptorpb .FieldDescriptorProto_TYPE_FIXED32 : intparser ,
440
+ descriptorpb .FieldDescriptorProto_TYPE_SFIXED32 : intparser ,
441
+ descriptorpb .FieldDescriptorProto_TYPE_SFIXED64 : intparser ,
442
+ descriptorpb .FieldDescriptorProto_TYPE_SINT32 : intparser ,
443
+ descriptorpb .FieldDescriptorProto_TYPE_SINT64 : intparser ,
444
+
445
+ descriptorpb .FieldDescriptorProto_TYPE_UINT32 : uintparser ,
446
+ descriptorpb .FieldDescriptorProto_TYPE_UINT64 : uintparser ,
372
447
}
373
448
374
449
// fieldDescriptor is an interface that allows to mock the desc.FieldDescriptor
0 commit comments