+const (
+ serviceNoReply = "null"
+)
+
+type RPC struct {
+ VPP vppapi.RPC
+
+ GoName string
+
+ Service *Service
+
+ MsgRequest *Message
+ MsgReply *Message
+ MsgStream *Message
+}
+
+func newRpc(file *File, service *Service, apitype vppapi.RPC) *RPC {
+ rpc := &RPC{
+ VPP: apitype,
+ GoName: camelCaseName(apitype.Request),
+ Service: service,
+ }
+ return rpc
+}
+
+func (rpc *RPC) resolveMessages(gen *Generator) error {
+ msg, ok := gen.messagesByName[rpc.VPP.Request]
+ if !ok {
+ return fmt.Errorf("rpc %v: no message for request type %v", rpc.GoName, rpc.VPP.Request)
+ }
+ rpc.MsgRequest = msg
+
+ if rpc.VPP.Reply != "" && rpc.VPP.Reply != serviceNoReply {
+ msg, ok := gen.messagesByName[rpc.VPP.Reply]
+ if !ok {
+ return fmt.Errorf("rpc %v: no message for reply type %v", rpc.GoName, rpc.VPP.Reply)
+ }
+ rpc.MsgReply = msg
+ }
+ if rpc.VPP.StreamMsg != "" {
+ msg, ok := gen.messagesByName[rpc.VPP.StreamMsg]
+ if !ok {
+ return fmt.Errorf("rpc %v: no message for stream type %v", rpc.GoName, rpc.VPP.StreamMsg)
+ }
+ rpc.MsgStream = msg
+ }
+ return nil
+}
+
+// GoIdent is a Go identifier, consisting of a name and import path.
+// The name is a single identifier and may not be a dot-qualified selector.
+type GoIdent struct {
+ GoName string
+ GoImportPath GoImportPath
+}
+
+func (id GoIdent) String() string {
+ return fmt.Sprintf("%q.%v", id.GoImportPath, id.GoName)
+}
+
+func newGoIdent(f *File, fullName string) GoIdent {
+ name := strings.TrimPrefix(fullName, string(f.PackageName)+".")
+ return GoIdent{
+ GoName: camelCaseName(name),
+ GoImportPath: f.GoImportPath,
+ }
+}
+
+// GoImportPath is a Go import path for a package.
+type GoImportPath string
+
+func (p GoImportPath) String() string {
+ return strconv.Quote(string(p))
+}
+
+func (p GoImportPath) Ident(s string) GoIdent {
+ return GoIdent{GoName: s, GoImportPath: p}
+}
+
+type GoPackageName string
+
+func cleanPackageName(name string) GoPackageName {
+ return GoPackageName(sanitizedName(name))
+}
+
+// baseName returns the last path element of the name, with the last dotted suffix removed.
+func baseName(name string) string {
+ // First, find the last element
+ if i := strings.LastIndex(name, "/"); i >= 0 {
+ name = name[i+1:]
+ }
+ // Now drop the suffix
+ if i := strings.LastIndex(name, "."); i >= 0 {
+ name = name[:i]