@@ -27,6 +27,8 @@ import (
2727 "time"
2828 "unsafe"
2929
30+ "github.com/cloudwego/thriftgo/generator/golang/streaming"
31+
3032 "github.com/cloudwego/dynamicgo/http"
3133 "github.com/cloudwego/dynamicgo/internal/json"
3234 "github.com/cloudwego/dynamicgo/internal/rt"
@@ -371,104 +373,137 @@ func addFunction(ctx context.Context, fn *parser.Function, tree *parser.Thrift,
371373
372374 }
373375
376+ st , err := streaming .ParseStreaming (fn )
377+ if err != nil {
378+ return err
379+ }
380+ isStreaming := st .ClientStreaming || st .ServerStreaming
381+
374382 var hasRequestBase bool
375383 var req * TypeDescriptor
376384 var resp * TypeDescriptor
377385
378386 // parse request field
379387 if opts .ParseFunctionMode != meta .ParseResponseOnly {
380- // WARN: only support single argument
381- reqAst := fn .Arguments [0 ]
382- req = & TypeDescriptor {
383- typ : STRUCT ,
384- struc : & StructDescriptor {
385- baseID : FieldID (math .MaxUint16 ),
386- ids : util.FieldIDMap {},
387- names : util.FieldNameMap {},
388- requires : make (RequiresBitmap , 1 ),
389- },
390- }
391-
392- reqType , err := parseType (ctx , reqAst .Type , tree , structsCache , 0 , opts , nextAnns , Request )
388+ req , hasRequestBase , err = parseRequest (ctx , isStreaming , fn , tree , structsCache , nextAnns , opts )
393389 if err != nil {
394390 return err
395391 }
396- if reqType .Type () == STRUCT {
397- for _ , f := range reqType .Struct ().names .All () {
398- x := (* FieldDescriptor )(f .Val )
399- if x .isRequestBase {
400- hasRequestBase = true
401- break
402- }
403- }
404- }
405- reqField := & FieldDescriptor {
406- name : reqAst .Name ,
407- id : FieldID (reqAst .ID ),
408- typ : reqType ,
409- }
410- req .Struct ().ids .Set (int32 (reqAst .ID ), unsafe .Pointer (reqField ))
411- req .Struct ().names .Set (reqAst .Name , unsafe .Pointer (reqField ))
412- req .Struct ().names .Build ()
413392 }
414393
415394 // parse response filed
416395 if opts .ParseFunctionMode != meta .ParseRequestOnly {
417- respAst := fn .FunctionType
418- resp = & TypeDescriptor {
419- typ : STRUCT ,
420- struc : & StructDescriptor {
421- baseID : FieldID (math .MaxUint16 ),
422- ids : util.FieldIDMap {},
423- names : util.FieldNameMap {},
424- requires : make (RequiresBitmap , 1 ),
425- },
426- }
427- respType , err := parseType (ctx , respAst , tree , structsCache , 0 , opts , nextAnns , Response )
396+ resp , err = parseResponse (ctx , isStreaming , fn , tree , structsCache , nextAnns , opts )
428397 if err != nil {
429398 return err
430399 }
431- respField := & FieldDescriptor {
432- typ : respType ,
433- }
434- resp .Struct ().ids .Set (0 , unsafe .Pointer (respField ))
435- // response has no name or id
436- resp .Struct ().names .Set ("" , unsafe .Pointer (respField ))
437-
438- // parse exceptions
439- if len (fn .Throws ) > 0 {
440- // only support single exception
441- exp := fn .Throws [0 ]
442- exceptionType , err := parseType (ctx , exp .Type , tree , structsCache , 0 , opts , nextAnns , Exception )
443- if err != nil {
444- return err
445- }
446- exceptionField := & FieldDescriptor {
447- name : exp .Name ,
448- alias : exp .Name ,
449- id : FieldID (exp .ID ),
450- // isException: true,
451- typ : exceptionType ,
452- }
453- resp .Struct ().ids .Set (int32 (exp .ID ), unsafe .Pointer (exceptionField ))
454- resp .Struct ().names .Set (exp .Name , unsafe .Pointer (exceptionField ))
455- }
456- resp .Struct ().names .Build ()
457400 }
458401
459402 fnDsc := & FunctionDescriptor {
460- name : fn .Name ,
461- oneway : fn .Oneway ,
462- request : req ,
463- response : resp ,
464- hasRequestBase : hasRequestBase ,
465- endpoints : enpdoints ,
466- annotations : annos ,
403+ name : fn .Name ,
404+ oneway : fn .Oneway ,
405+ request : req ,
406+ response : resp ,
407+ hasRequestBase : hasRequestBase ,
408+ endpoints : enpdoints ,
409+ annotations : annos ,
410+ isWithoutWrapping : isStreaming ,
467411 }
468412 sDsc .functions [fn .Name ] = fnDsc
469413 return nil
470414}
471415
416+ func parseRequest (ctx context.Context , isStreaming bool , fn * parser.Function , tree * parser.Thrift , structsCache compilingCache , nextAnns []parser.Annotation , opts Options ) (req * TypeDescriptor , hasRequestBase bool , err error ) {
417+ // WARN: only support single argument
418+ reqAst := fn .Arguments [0 ]
419+ reqType , err := parseType (ctx , reqAst .Type , tree , structsCache , 0 , opts , nextAnns , Request )
420+ if err != nil {
421+ return nil , hasRequestBase , err
422+ }
423+ if reqType .Type () == STRUCT {
424+ for _ , f := range reqType .Struct ().names .All () {
425+ x := (* FieldDescriptor )(f .Val )
426+ if x .isRequestBase {
427+ hasRequestBase = true
428+ break
429+ }
430+ }
431+ }
432+
433+ if isStreaming {
434+ return reqType , hasRequestBase , nil
435+ }
436+
437+ // wrap with a struct
438+ wrappedTyDsc := & TypeDescriptor {
439+ typ : STRUCT ,
440+ struc : & StructDescriptor {
441+ baseID : FieldID (math .MaxUint16 ),
442+ ids : util.FieldIDMap {},
443+ names : util.FieldNameMap {},
444+ requires : make (RequiresBitmap , 1 ),
445+ },
446+ }
447+ reqField := & FieldDescriptor {
448+ name : reqAst .Name ,
449+ id : FieldID (reqAst .ID ),
450+ typ : reqType ,
451+ }
452+ wrappedTyDsc .Struct ().ids .Set (int32 (reqAst .ID ), unsafe .Pointer (reqField ))
453+ wrappedTyDsc .Struct ().names .Set (reqAst .Name , unsafe .Pointer (reqField ))
454+ wrappedTyDsc .Struct ().names .Build ()
455+ return wrappedTyDsc , hasRequestBase , nil
456+ }
457+
458+ func parseResponse (ctx context.Context , isStreaming bool , fn * parser.Function , tree * parser.Thrift , structsCache compilingCache , nextAnns []parser.Annotation , opts Options ) (resp * TypeDescriptor , err error ) {
459+ respAst := fn .FunctionType
460+ respType , err := parseType (ctx , respAst , tree , structsCache , 0 , opts , nextAnns , Response )
461+ if err != nil {
462+ return nil , err
463+ }
464+
465+ if isStreaming {
466+ return respType , nil
467+ }
468+
469+ wrappedResp := & TypeDescriptor {
470+ typ : STRUCT ,
471+ struc : & StructDescriptor {
472+ baseID : FieldID (math .MaxUint16 ),
473+ ids : util.FieldIDMap {},
474+ names : util.FieldNameMap {},
475+ requires : make (RequiresBitmap , 1 ),
476+ },
477+ }
478+ respField := & FieldDescriptor {
479+ typ : respType ,
480+ }
481+ wrappedResp .Struct ().ids .Set (0 , unsafe .Pointer (respField ))
482+ // response has no name or id
483+ wrappedResp .Struct ().names .Set ("" , unsafe .Pointer (respField ))
484+
485+ // parse exceptions
486+ if len (fn .Throws ) > 0 {
487+ // only support single exception
488+ exp := fn .Throws [0 ]
489+ exceptionType , err := parseType (ctx , exp .Type , tree , structsCache , 0 , opts , nextAnns , Exception )
490+ if err != nil {
491+ return nil , err
492+ }
493+ exceptionField := & FieldDescriptor {
494+ name : exp .Name ,
495+ alias : exp .Name ,
496+ id : FieldID (exp .ID ),
497+ // isException: true,
498+ typ : exceptionType ,
499+ }
500+ wrappedResp .Struct ().ids .Set (int32 (exp .ID ), unsafe .Pointer (exceptionField ))
501+ wrappedResp .Struct ().names .Set (exp .Name , unsafe .Pointer (exceptionField ))
502+ }
503+ wrappedResp .Struct ().names .Build ()
504+ return wrappedResp , nil
505+ }
506+
472507// reuse builtin types
473508var builtinTypes = map [string ]* TypeDescriptor {
474509 "void" : {name : "void" , typ : VOID , struc : new (StructDescriptor )},
0 commit comments