@@ -174,8 +174,13 @@ func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.
174
174
175
175
g .P ("// This is a compile-time assertion to ensure that this generated file" )
176
176
g .P ("// is compatible with the grpc package it is being compiled against." )
177
- g .P ("// Requires gRPC-Go v1.62.0 or later." )
178
- g .P ("const _ = " , grpcPackage .Ident ("SupportPackageIsVersion8" )) // When changing, update version number above.
177
+ if * useGenericStreams {
178
+ g .P ("// Requires gRPC-Go v1.64.0 or later." )
179
+ g .P ("const _ = " , grpcPackage .Ident ("SupportPackageIsVersion9" ))
180
+ } else {
181
+ g .P ("// Requires gRPC-Go v1.62.0 or later." )
182
+ g .P ("const _ = " , grpcPackage .Ident ("SupportPackageIsVersion8" )) // When changing, update version number above.
183
+ }
179
184
g .P ()
180
185
for _ , service := range file .Services {
181
186
genService (gen , file , g , service )
@@ -299,12 +304,27 @@ func clientSignature(g *protogen.GeneratedFile, method *protogen.Method) string
299
304
if ! method .Desc .IsStreamingClient () && ! method .Desc .IsStreamingServer () {
300
305
s += "*" + g .QualifiedGoIdent (method .Output .GoIdent )
301
306
} else {
302
- s += method .Parent .GoName + "_" + method .GoName + "Client"
307
+ if * useGenericStreams {
308
+ s += clientStreamInterface (g , method )
309
+ } else {
310
+ s += method .Parent .GoName + "_" + method .GoName + "Client"
311
+ }
303
312
}
304
313
s += ", error)"
305
314
return s
306
315
}
307
316
317
+ func clientStreamInterface (g * protogen.GeneratedFile , method * protogen.Method ) string {
318
+ typeParam := g .QualifiedGoIdent (method .Input .GoIdent ) + ", " + g .QualifiedGoIdent (method .Output .GoIdent )
319
+ if method .Desc .IsStreamingClient () && method .Desc .IsStreamingServer () {
320
+ return g .QualifiedGoIdent (grpcPackage .Ident ("BidiStreamingClient" )) + "[" + typeParam + "]"
321
+ } else if method .Desc .IsStreamingClient () {
322
+ return g .QualifiedGoIdent (grpcPackage .Ident ("ClientStreamingClient" )) + "[" + typeParam + "]"
323
+ } else { // i.e. if method.Desc.IsStreamingServer()
324
+ return g .QualifiedGoIdent (grpcPackage .Ident ("ServerStreamingClient" )) + "[" + g .QualifiedGoIdent (method .Output .GoIdent ) + "]"
325
+ }
326
+ }
327
+
308
328
func genClientMethod (gen * protogen.Plugin , file * protogen.File , g * protogen.GeneratedFile , method * protogen.Method , index int ) {
309
329
service := method .Parent
310
330
fmSymbol := helper .formatFullMethodSymbol (service , method )
@@ -323,11 +343,17 @@ func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
323
343
g .P ()
324
344
return
325
345
}
326
- streamType := unexport (service .GoName ) + method .GoName + "Client"
346
+
347
+ streamImpl := unexport (service .GoName ) + method .GoName + "Client"
348
+ if * useGenericStreams {
349
+ typeParam := g .QualifiedGoIdent (method .Input .GoIdent ) + ", " + g .QualifiedGoIdent (method .Output .GoIdent )
350
+ streamImpl = g .QualifiedGoIdent (grpcPackage .Ident ("GenericClientStream" )) + "[" + typeParam + "]"
351
+ }
352
+
327
353
serviceDescVar := service .GoName + "_ServiceDesc"
328
354
g .P ("stream, err := c.cc.NewStream(ctx, &" , serviceDescVar , ".Streams[" , index , `], ` , fmSymbol , `, cOpts...)` )
329
355
g .P ("if err != nil { return nil, err }" )
330
- g .P ("x := &" , streamType , "{stream}" )
356
+ g .P ("x := &" , streamImpl , "{ClientStream: stream}" )
331
357
if ! method .Desc .IsStreamingClient () {
332
358
g .P ("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }" )
333
359
g .P ("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }" )
@@ -336,11 +362,20 @@ func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
336
362
g .P ("}" )
337
363
g .P ()
338
364
365
+ // Auxiliary types aliases, for backwards compatibility.
366
+ if * useGenericStreams {
367
+ g .P ("// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name." )
368
+ g .P ("type " , service .GoName , "_" , method .GoName , "Client = " , clientStreamInterface (g , method ))
369
+ g .P ()
370
+ return
371
+ }
372
+
373
+ // Stream auxiliary types and methods, if we're not taking advantage of the
374
+ // pre-implemented generic types and their methods.
339
375
genSend := method .Desc .IsStreamingClient ()
340
376
genRecv := method .Desc .IsStreamingServer ()
341
377
genCloseAndRecv := ! method .Desc .IsStreamingServer ()
342
378
343
- // Stream auxiliary types and methods.
344
379
g .P ("type " , service .GoName , "_" , method .GoName , "Client interface {" )
345
380
if genSend {
346
381
g .P ("Send(*" , method .Input .GoIdent , ") error" )
@@ -355,27 +390,27 @@ func genClientMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
355
390
g .P ("}" )
356
391
g .P ()
357
392
358
- g .P ("type " , streamType , " struct {" )
393
+ g .P ("type " , streamImpl , " struct {" )
359
394
g .P (grpcPackage .Ident ("ClientStream" ))
360
395
g .P ("}" )
361
396
g .P ()
362
397
363
398
if genSend {
364
- g .P ("func (x *" , streamType , ") Send(m *" , method .Input .GoIdent , ") error {" )
399
+ g .P ("func (x *" , streamImpl , ") Send(m *" , method .Input .GoIdent , ") error {" )
365
400
g .P ("return x.ClientStream.SendMsg(m)" )
366
401
g .P ("}" )
367
402
g .P ()
368
403
}
369
404
if genRecv {
370
- g .P ("func (x *" , streamType , ") Recv() (*" , method .Output .GoIdent , ", error) {" )
405
+ g .P ("func (x *" , streamImpl , ") Recv() (*" , method .Output .GoIdent , ", error) {" )
371
406
g .P ("m := new(" , method .Output .GoIdent , ")" )
372
407
g .P ("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }" )
373
408
g .P ("return m, nil" )
374
409
g .P ("}" )
375
410
g .P ()
376
411
}
377
412
if genCloseAndRecv {
378
- g .P ("func (x *" , streamType , ") CloseAndRecv() (*" , method .Output .GoIdent , ", error) {" )
413
+ g .P ("func (x *" , streamImpl , ") CloseAndRecv() (*" , method .Output .GoIdent , ", error) {" )
379
414
g .P ("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }" )
380
415
g .P ("m := new(" , method .Output .GoIdent , ")" )
381
416
g .P ("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }" )
@@ -396,7 +431,11 @@ func serverSignature(g *protogen.GeneratedFile, method *protogen.Method) string
396
431
reqArgs = append (reqArgs , "*" + g .QualifiedGoIdent (method .Input .GoIdent ))
397
432
}
398
433
if method .Desc .IsStreamingClient () || method .Desc .IsStreamingServer () {
399
- reqArgs = append (reqArgs , method .Parent .GoName + "_" + method .GoName + "Server" )
434
+ if * useGenericStreams {
435
+ reqArgs = append (reqArgs , serverStreamInterface (g , method ))
436
+ } else {
437
+ reqArgs = append (reqArgs , method .Parent .GoName + "_" + method .GoName + "Server" )
438
+ }
400
439
}
401
440
return method .GoName + "(" + strings .Join (reqArgs , ", " ) + ") " + ret
402
441
}
@@ -442,6 +481,17 @@ func genServiceDesc(file *protogen.File, g *protogen.GeneratedFile, serviceDescV
442
481
g .P ()
443
482
}
444
483
484
+ func serverStreamInterface (g * protogen.GeneratedFile , method * protogen.Method ) string {
485
+ typeParam := g .QualifiedGoIdent (method .Input .GoIdent ) + ", " + g .QualifiedGoIdent (method .Output .GoIdent )
486
+ if method .Desc .IsStreamingClient () && method .Desc .IsStreamingServer () {
487
+ return g .QualifiedGoIdent (grpcPackage .Ident ("BidiStreamingServer" )) + "[" + typeParam + "]"
488
+ } else if method .Desc .IsStreamingClient () {
489
+ return g .QualifiedGoIdent (grpcPackage .Ident ("ClientStreamingServer" )) + "[" + typeParam + "]"
490
+ } else { // i.e. if method.Desc.IsStreamingServer()
491
+ return g .QualifiedGoIdent (grpcPackage .Ident ("ServerStreamingServer" )) + "[" + g .QualifiedGoIdent (method .Output .GoIdent ) + "]"
492
+ }
493
+ }
494
+
445
495
func genServerMethod (gen * protogen.Plugin , file * protogen.File , g * protogen.GeneratedFile , method * protogen.Method , hnameFuncNameFormatter func (string ) string ) string {
446
496
service := method .Parent
447
497
hname := fmt .Sprintf ("_%s_%s_Handler" , service .GoName , method .GoName )
@@ -464,23 +514,38 @@ func genServerMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
464
514
g .P ()
465
515
return hname
466
516
}
467
- streamType := unexport (service .GoName ) + method .GoName + "Server"
517
+
518
+ streamImpl := unexport (service .GoName ) + method .GoName + "Server"
519
+ if * useGenericStreams {
520
+ typeParam := g .QualifiedGoIdent (method .Input .GoIdent ) + ", " + g .QualifiedGoIdent (method .Output .GoIdent )
521
+ streamImpl = g .QualifiedGoIdent (grpcPackage .Ident ("GenericServerStream" )) + "[" + typeParam + "]"
522
+ }
523
+
468
524
g .P ("func " , hnameFuncNameFormatter (hname ), "(srv interface{}, stream " , grpcPackage .Ident ("ServerStream" ), ") error {" )
469
525
if ! method .Desc .IsStreamingClient () {
470
526
g .P ("m := new(" , method .Input .GoIdent , ")" )
471
527
g .P ("if err := stream.RecvMsg(m); err != nil { return err }" )
472
- g .P ("return srv.(" , service .GoName , "Server)." , method .GoName , "(m, &" , streamType , "{stream})" )
528
+ g .P ("return srv.(" , service .GoName , "Server)." , method .GoName , "(m, &" , streamImpl , "{ServerStream: stream})" )
473
529
} else {
474
- g .P ("return srv.(" , service .GoName , "Server)." , method .GoName , "(&" , streamType , "{stream})" )
530
+ g .P ("return srv.(" , service .GoName , "Server)." , method .GoName , "(&" , streamImpl , "{ServerStream: stream})" )
475
531
}
476
532
g .P ("}" )
477
533
g .P ()
478
534
535
+ // Auxiliary types aliases, for backwards compatibility.
536
+ if * useGenericStreams {
537
+ g .P ("// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name." )
538
+ g .P ("type " , service .GoName , "_" , method .GoName , "Server = " , serverStreamInterface (g , method ))
539
+ g .P ()
540
+ return hname
541
+ }
542
+
543
+ // Stream auxiliary types and methods, if we're not taking advantage of the
544
+ // pre-implemented generic types and their methods.
479
545
genSend := method .Desc .IsStreamingServer ()
480
546
genSendAndClose := ! method .Desc .IsStreamingServer ()
481
547
genRecv := method .Desc .IsStreamingClient ()
482
548
483
- // Stream auxiliary types and methods.
484
549
g .P ("type " , service .GoName , "_" , method .GoName , "Server interface {" )
485
550
if genSend {
486
551
g .P ("Send(*" , method .Output .GoIdent , ") error" )
@@ -495,25 +560,25 @@ func genServerMethod(gen *protogen.Plugin, file *protogen.File, g *protogen.Gene
495
560
g .P ("}" )
496
561
g .P ()
497
562
498
- g .P ("type " , streamType , " struct {" )
563
+ g .P ("type " , streamImpl , " struct {" )
499
564
g .P (grpcPackage .Ident ("ServerStream" ))
500
565
g .P ("}" )
501
566
g .P ()
502
567
503
568
if genSend {
504
- g .P ("func (x *" , streamType , ") Send(m *" , method .Output .GoIdent , ") error {" )
569
+ g .P ("func (x *" , streamImpl , ") Send(m *" , method .Output .GoIdent , ") error {" )
505
570
g .P ("return x.ServerStream.SendMsg(m)" )
506
571
g .P ("}" )
507
572
g .P ()
508
573
}
509
574
if genSendAndClose {
510
- g .P ("func (x *" , streamType , ") SendAndClose(m *" , method .Output .GoIdent , ") error {" )
575
+ g .P ("func (x *" , streamImpl , ") SendAndClose(m *" , method .Output .GoIdent , ") error {" )
511
576
g .P ("return x.ServerStream.SendMsg(m)" )
512
577
g .P ("}" )
513
578
g .P ()
514
579
}
515
580
if genRecv {
516
- g .P ("func (x *" , streamType , ") Recv() (*" , method .Input .GoIdent , ", error) {" )
581
+ g .P ("func (x *" , streamImpl , ") Recv() (*" , method .Input .GoIdent , ", error) {" )
517
582
g .P ("m := new(" , method .Input .GoIdent , ")" )
518
583
g .P ("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }" )
519
584
g .P ("return m, nil" )
0 commit comments