github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/cmd/internal/protobuf/v3/service.go (about)

     1  package v3
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/iancoleman/strcase"
     6  	"github.com/unionj-cloud/go-doudou/cmd/internal/astutils"
     7  	"github.com/unionj-cloud/go-doudou/toolkit/constants"
     8  	"github.com/unionj-cloud/go-doudou/version"
     9  	"reflect"
    10  	"strings"
    11  	"time"
    12  )
    13  
    14  // service SearchService {
    15  //   rpc Search(SearchRequest) returns (SearchResponse);
    16  // }
    17  
    18  const Syntax = "proto3"
    19  
    20  type Service struct {
    21  	Name      string
    22  	Package   string
    23  	GoPackage string
    24  	Syntax    string
    25  	// go-doudou version
    26  	Version  string
    27  	ProtoVer string
    28  	Rpcs     []Rpc
    29  	Messages []Message
    30  	Enums    []Enum
    31  	Comments []string
    32  	Imports  []string
    33  }
    34  
    35  func NewService(name, goPackage string) Service {
    36  	return Service{
    37  		Name:      strcase.ToCamel(name) + "Service",
    38  		Package:   strcase.ToSnake(name),
    39  		GoPackage: goPackage,
    40  		Syntax:    Syntax,
    41  		Version:   version.Release,
    42  		ProtoVer:  fmt.Sprintf("v%s", time.Now().Local().Format(constants.FORMAT10)),
    43  	}
    44  }
    45  
    46  type StreamType int
    47  
    48  const (
    49  	biStream = iota + 1
    50  	clientStream
    51  	serverStream
    52  )
    53  
    54  type Rpc struct {
    55  	Name       string
    56  	Request    Message
    57  	Response   Message
    58  	Comments   []string
    59  	StreamType StreamType
    60  }
    61  
    62  func NewRpc(method astutils.MethodMeta) Rpc {
    63  	rpcName := strcase.ToCamel(method.Name) + "Rpc"
    64  	rpcRequest := newRequest(rpcName, method.Params)
    65  	if reflect.DeepEqual(rpcRequest, Empty) {
    66  		ImportStore["google/protobuf/empty.proto"] = struct{}{}
    67  	}
    68  	if !strings.HasPrefix(rpcRequest.Name, "stream ") {
    69  		if _, ok := MessageStore[rpcRequest.Name]; !ok {
    70  			MessageStore[rpcRequest.Name] = rpcRequest
    71  		}
    72  	}
    73  	rpcResponse := newResponse(rpcName, method.Results)
    74  	if reflect.DeepEqual(rpcResponse, Empty) {
    75  		ImportStore["google/protobuf/empty.proto"] = struct{}{}
    76  	}
    77  	if !strings.HasPrefix(rpcResponse.Name, "stream ") {
    78  		if _, ok := MessageStore[rpcResponse.Name]; !ok {
    79  			MessageStore[rpcResponse.Name] = rpcResponse
    80  		}
    81  	}
    82  	var st StreamType
    83  	if strings.HasPrefix(rpcRequest.Name, "stream ") && strings.HasPrefix(rpcResponse.Name, "stream ") {
    84  		st = biStream
    85  	} else if strings.HasPrefix(rpcRequest.Name, "stream ") {
    86  		st = clientStream
    87  	} else if strings.HasPrefix(rpcResponse.Name, "stream ") {
    88  		st = serverStream
    89  	}
    90  	return Rpc{
    91  		Name:       rpcName,
    92  		Request:    rpcRequest,
    93  		Response:   rpcResponse,
    94  		Comments:   method.Comments,
    95  		StreamType: st,
    96  	}
    97  }
    98  
    99  func newRequest(rpcName string, params []astutils.FieldMeta) Message {
   100  	if len(params) == 0 {
   101  		return Empty
   102  	}
   103  	if len(params) == 1 && params[0].Type == "context.Context" {
   104  		return Empty
   105  	}
   106  	if params[0].Type == "context.Context" {
   107  		params = params[1:]
   108  	}
   109  	if len(params) == 1 {
   110  		if m, ok := MessageOf(params[0].Type).(Message); ok && m.IsTopLevel {
   111  			if strings.HasPrefix(params[0].Name, "stream") {
   112  				m.Name = "stream " + m.Name
   113  			}
   114  			return m
   115  		}
   116  	}
   117  	var fields []Field
   118  	for i, field := range params {
   119  		fields = append(fields, newField(field, i+1))
   120  	}
   121  	return Message{
   122  		Name:       strcase.ToCamel(rpcName + "Request"),
   123  		Fields:     fields,
   124  		IsTopLevel: true,
   125  	}
   126  }
   127  
   128  func newResponse(rpcName string, params []astutils.FieldMeta) Message {
   129  	if len(params) == 0 {
   130  		return Empty
   131  	}
   132  	if len(params) == 1 && params[0].Type == "error" {
   133  		return Empty
   134  	}
   135  	if params[len(params)-1].Type == "error" {
   136  		params = params[:len(params)-1]
   137  	}
   138  	if len(params) == 1 {
   139  		if m, ok := MessageOf(params[0].Type).(Message); ok && m.IsTopLevel {
   140  			if strings.HasPrefix(params[0].Name, "stream") {
   141  				m.Name = "stream " + m.Name
   142  			}
   143  			return m
   144  		}
   145  	}
   146  	var fields []Field
   147  	for i, field := range params {
   148  		fields = append(fields, newField(field, i+1))
   149  	}
   150  	return Message{
   151  		Name:       strcase.ToCamel(rpcName + "Response"),
   152  		Fields:     fields,
   153  		IsTopLevel: true,
   154  	}
   155  }