diff options
author | baude <bbaude@redhat.com> | 2018-03-26 09:39:14 -0500 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-04-23 14:29:45 +0000 |
commit | 8493dba23c73617d9529b7ca13b400d50ac6f455 (patch) | |
tree | c0de0c67334b9fa7166e01cae95dc560c1e2455a /vendor/github.com/varlink/go/cmd | |
parent | cf1d884ffa45b342f38a78189bbd86186ce6cbfe (diff) | |
download | podman-8493dba23c73617d9529b7ca13b400d50ac6f455.tar.gz podman-8493dba23c73617d9529b7ca13b400d50ac6f455.tar.bz2 podman-8493dba23c73617d9529b7ca13b400d50ac6f455.zip |
Initial varlink implementation
Signed-off-by: baude <bbaude@redhat.com>
Closes: #627
Approved by: mheon
Diffstat (limited to 'vendor/github.com/varlink/go/cmd')
3 files changed, 521 insertions, 0 deletions
diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go new file mode 100644 index 000000000..aa3a8565f --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/generator_test.go @@ -0,0 +1,85 @@ +package main + +import ( + "strings" + "testing" +) + +func expect(t *testing.T, expected string, returned string) { + if strings.Compare(returned, expected) != 0 { + t.Fatalf("Expected(%d): `%s`\nGot(%d): `%s`\n", + len(expected), expected, + len(returned), returned) + } +} + +func TestIDLParser(t *testing.T) { + pkgname, b, err := generateTemplate(` +# Interface to jump a spacecraft to another point in space. The +# FTL Drive is the propulsion system to achieve faster-than-light +# travel through space. A ship making a properly calculated +# jump can arrive safely in planetary orbit, or alongside other +# ships or spaceborne objects. +interface org.example.ftl + +# The current state of the FTL drive and the amount of fuel +# available to jump. +type DriveCondition ( + state: (idle, spooling, busy), + booster: bool, + active_engines: [](id: int, state: bool), + tylium_level: int +) + +# Speed, trajectory and jump duration is calculated prior to +# activating the FTL drive. +type DriveConfiguration ( + speed: int, + trajectory: int, + duration: int +) + +# The galactic coordinates use the Sun as the origin. Galactic +# longitude is measured with primary direction from the Sun to +# the center of the galaxy in the galactic plane, while the +# galactic latitude measures the angle of the object above the +# galactic plane. +type Coordinate ( + longitude: float, + latitude: float, + distance: int +) + +# Monitor the drive. The method will reply with an update whenever +# the drive's state changes +method Monitor() -> (condition: DriveCondition) + +# Calculate the drive's jump parameters from the current +# position to the target position in the galaxy +method CalculateConfiguration( + current: Coordinate, + target: Coordinate +) -> (configuration: DriveConfiguration) + +# Jump to the calculated point in space +method Jump(configuration: DriveConfiguration) -> () + +# There is not enough tylium to jump with the given parameters +error NotEnoughEnergy () + +# The supplied parameters are outside the supported range +error ParameterOutOfRange (field: string) + +# some more coverage +method Foo(interface: string) -> (ret: (go: string, switch: bool, more: (t:bool, f:bool))) + `) + + if err != nil { + t.Fatalf("Error parsing %v", err) + } + expect(t, "orgexampleftl", pkgname) + if len(b) <= 0 { + t.Fatal("No generated go source") + } + // FIXME: compare b.String() against expected output +} diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go new file mode 100644 index 000000000..1bcdb78de --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go @@ -0,0 +1,294 @@ +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/varlink/go/varlink/idl" +) + +var goKeywords = map[string]struct{}{ + "break": {}, + "case": {}, + "chan": {}, + "const": {}, + "continue": {}, + "default": {}, + "defer": {}, + "else": {}, + "fallthrough": {}, + "for": {}, + "func": {}, + "go": {}, + "goto": {}, + "if": {}, + "import": {}, + "interface": {}, + "map": {}, + "package": {}, + "range": {}, + "return": {}, + "select": {}, + "struct": {}, + "switch": {}, + "type": {}, + "var": {}, +} + +func sanitizeGoName(name string) string { + if _, ok := goKeywords[name]; !ok { + return name + } + return name + "_" +} + +func writeType(b *bytes.Buffer, t *idl.Type, json bool, ident int) { + switch t.Kind { + case idl.TypeBool: + b.WriteString("bool") + + case idl.TypeInt: + b.WriteString("int64") + + case idl.TypeFloat: + b.WriteString("float64") + + case idl.TypeString, idl.TypeEnum: + b.WriteString("string") + + case idl.TypeArray: + b.WriteString("[]") + writeType(b, t.ElementType, json, ident) + + case idl.TypeMaybe: + b.WriteString("*") + writeType(b, t.ElementType, json, ident) + + case idl.TypeAlias: + b.WriteString(t.Alias) + + case idl.TypeStruct: + b.WriteString("struct{\n") + for _, field := range t.Fields { + for i := 0; i < ident+1; i++ { + b.WriteString("\t") + } + + b.WriteString(strings.Title(field.Name) + " ") + writeType(b, field.Type, json, ident+1) + if json { + b.WriteString(" `json:\"" + field.Name + "\"`") + } + b.WriteString("\n") + } + for i := 0; i < ident; i++ { + b.WriteString("\t") + } + b.WriteString("}") + } +} + +func generateTemplate(description string) (string, []byte, error) { + description = strings.TrimRight(description, "\n") + + midl, err := idl.New(description) + if err != nil { + return "", nil, err + } + + pkgname := strings.Replace(midl.Name, ".", "", -1) + + var b bytes.Buffer + b.WriteString("// Generated with github.com/varlink/go/cmd/varlink-go-interface-generator\n") + b.WriteString("package " + pkgname + "\n\n") + b.WriteString(`import "github.com/varlink/go/varlink"` + "\n\n") + + // Type declarations + for _, a := range midl.Aliases { + b.WriteString("type " + a.Name + " ") + writeType(&b, a.Type, true, 0) + b.WriteString("\n\n") + } + + // Local interface with all methods + b.WriteString("type " + pkgname + "Interface interface {\n") + for _, m := range midl.Methods { + b.WriteString("\t" + m.Name + "(c VarlinkCall") + for _, field := range m.In.Fields { + b.WriteString(", " + strings.Title(field.Name) + " ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error\n") + } + b.WriteString("}\n\n") + + // Local object with all methods + b.WriteString("type VarlinkCall struct{ varlink.Call }\n\n") + + // Reply methods for all varlink errors + for _, e := range midl.Errors { + b.WriteString("func (c *VarlinkCall) Reply" + e.Name + "(") + for i, field := range e.Type.Fields { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(sanitizeGoName(field.Name) + " ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n") + if len(e.Type.Fields) > 0 { + b.WriteString("\tvar out ") + writeType(&b, e.Type, true, 1) + b.WriteString("\n") + for _, field := range e.Type.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray: + b.WriteString("\tout." + strings.Title(field.Name) + " = ") + writeType(&b, field.Type, true, 1) + b.WriteString("(" + sanitizeGoName(field.Name) + ")\n") + + default: + b.WriteString("\tout." + strings.Title(field.Name) + " = " + sanitizeGoName(field.Name) + "\n") + } + } + b.WriteString("\treturn c.ReplyError(\"" + midl.Name + "." + e.Name + "\", &out)\n") + } else { + b.WriteString("\treturn c.ReplyError(\"" + midl.Name + "." + e.Name + "\", nil)\n") + } + b.WriteString("}\n\n") + } + + // Reply methods for all varlink methods + for _, m := range midl.Methods { + b.WriteString("func (c *VarlinkCall) Reply" + m.Name + "(") + for i, field := range m.Out.Fields { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(sanitizeGoName(field.Name) + " ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n") + if len(m.Out.Fields) > 0 { + b.WriteString("\tvar out ") + writeType(&b, m.Out, true, 1) + b.WriteString("\n") + for _, field := range m.Out.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray: + b.WriteString("\tout." + strings.Title(field.Name) + " = ") + writeType(&b, field.Type, true, 1) + b.WriteString("(" + sanitizeGoName(field.Name) + ")\n") + + default: + b.WriteString("\tout." + strings.Title(field.Name) + " = " + sanitizeGoName(field.Name) + "\n") + } + } + b.WriteString("\treturn c.Reply(&out)\n") + } else { + b.WriteString("\treturn c.Reply(nil)\n") + } + b.WriteString("}\n\n") + } + + // Dummy methods for all varlink methods + for _, m := range midl.Methods { + b.WriteString("func (s *VarlinkInterface) " + m.Name + "(c VarlinkCall") + for _, field := range m.In.Fields { + b.WriteString(", " + sanitizeGoName(field.Name) + " ") + writeType(&b, field.Type, false, 1) + } + b.WriteString(") error {\n" + + "\treturn c.ReplyMethodNotImplemented(\"" + m.Name + "\")\n" + + "}\n\n") + } + + // Method call dispatcher + b.WriteString("func (s *VarlinkInterface) VarlinkDispatch(call varlink.Call, methodname string) error {\n" + + "\tswitch methodname {\n") + for _, m := range midl.Methods { + b.WriteString("\tcase \"" + m.Name + "\":\n") + if len(m.In.Fields) > 0 { + b.WriteString("\t\tvar in ") + writeType(&b, m.In, true, 2) + b.WriteString("\n") + b.WriteString("\t\terr := call.GetParameters(&in)\n" + + "\t\tif err != nil {\n" + + "\t\t\treturn call.ReplyInvalidParameter(\"parameters\")\n" + + "\t\t}\n") + b.WriteString("\t\treturn s." + pkgname + "Interface." + m.Name + "(VarlinkCall{call}") + if len(m.In.Fields) > 0 { + for _, field := range m.In.Fields { + switch field.Type.Kind { + case idl.TypeStruct, idl.TypeArray: + b.WriteString(", ") + writeType(&b, field.Type, false, 2) + b.WriteString("(in." + strings.Title(field.Name) + ")") + + default: + b.WriteString(", in." + strings.Title(field.Name)) + } + } + } + b.WriteString(")\n") + } else { + b.WriteString("\t\treturn s." + pkgname + "Interface." + m.Name + "(VarlinkCall{call})\n") + } + b.WriteString("\n") + } + b.WriteString("\tdefault:\n" + + "\t\treturn call.ReplyMethodNotFound(methodname)\n" + + "\t}\n" + + "}\n") + + // Varlink interface name + b.WriteString("func (s *VarlinkInterface) VarlinkGetName() string {\n" + + "\treturn `" + midl.Name + "`\n" + "}\n\n") + + // Varlink interface description + b.WriteString("func (s *VarlinkInterface) VarlinkGetDescription() string {\n" + + "\treturn `" + midl.Description + "\n`\n}\n\n") + + b.WriteString("type VarlinkInterface struct {\n" + + "\t" + pkgname + "Interface\n" + + "}\n\n") + + b.WriteString("func VarlinkNew(m " + pkgname + "Interface) *VarlinkInterface {\n" + + "\treturn &VarlinkInterface{m}\n" + + "}\n") + + return pkgname, b.Bytes(), nil +} + +func generateFile(varlinkFile string) { + file, err := ioutil.ReadFile(varlinkFile) + if err != nil { + fmt.Fprintf(os.Stderr, "Error reading file '%s': %s\n", varlinkFile, err) + os.Exit(1) + } + + pkgname, b, err := generateTemplate(string(file)) + if err != nil { + fmt.Fprintf(os.Stderr, "Error parsing file '%s': %s\n", varlinkFile, err) + os.Exit(1) + } + + filename := path.Dir(varlinkFile) + "/" + pkgname + ".go" + err = ioutil.WriteFile(filename, b, 0660) + if err != nil { + fmt.Fprintf(os.Stderr, "Error writing file '%s': %s\n", filename, err) + os.Exit(1) + } +} + +func main() { + if len(os.Args) != 2 { + fmt.Printf("Usage: %s <file>\n", os.Args[0]) + os.Exit(1) + } + generateFile(os.Args[1]) +} diff --git a/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go b/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go new file mode 100644 index 000000000..dfbec5fb2 --- /dev/null +++ b/vendor/github.com/varlink/go/cmd/varlink-go-type-generator/main.go @@ -0,0 +1,142 @@ +package main + +import ( + "fmt" + "go/ast" + "go/importer" + "go/parser" + "go/token" + "go/types" + "log" + "os" +) + +func GoToVarlinkType(t types.Type) string { + switch u := t.(type) { + case *types.Basic: + if u.Info()&types.IsBoolean != 0 { + return "bool" + } + if u.Info()&types.IsInteger != 0 { + return "int" + } + if u.Info()&types.IsFloat != 0 { + return "float" + } + if u.Info()&types.IsString != 0 { + return "string" + } + return fmt.Sprintf("<<<%s>>>", t.String()) + + case *types.Named: + return u.Obj().Name() + + case *types.Map: + return fmt.Sprintf("<<<%s>>>", u.String()) + + case *types.Interface: + return fmt.Sprintf("<<<%s>>>", u.String()) + + case *types.Pointer: + return fmt.Sprintf("?%s", GoToVarlinkType(u.Elem())) + + case *types.Array: + return fmt.Sprintf("[]%s", GoToVarlinkType(u.Elem())) + + case *types.Slice: + return fmt.Sprintf("[]%s", GoToVarlinkType(u.Elem())) + + default: + return fmt.Sprintf("<<<%T %s>>>", t, u) + } + + return t.String() +} + +func PrintDefsUses(name string, fset *token.FileSet, files []*ast.File) error { + conf := types.Config{ + Importer: importer.Default(), + FakeImportC: true, + } + + info := &types.Info{ + Defs: make(map[*ast.Ident]types.Object), + } + + _, err := conf.Check(name, fset, files, info) + if err != nil { + return err // type error + } + + seen := map[string]interface{}{} + + for id, obj := range info.Defs { + if obj == nil { + continue + } + + if _, ok := seen[id.Name]; ok { + continue + } + + /* + if !obj.Exported() || obj.Pkg().Name() != name { + continue + } + */ + switch f := obj.Type().Underlying().(type) { + case *types.Struct: + if f.NumFields() > 0 { + fmt.Printf("type %s (\n", id.Name) + fmt.Printf("\t%s: %s", + f.Field(0).Name(), GoToVarlinkType(f.Field(0).Type())) + for i := 1; i < f.NumFields(); i++ { + fmt.Printf(",\n\t%s: %s", + f.Field(i).Name(), GoToVarlinkType(f.Field(i).Type())) + } + fmt.Printf("\n)\n\n") + } + } + seen[id.Name] = nil + } + + return nil +} + +func main() { + + path := os.Args[1] + fs := token.NewFileSet() + + if stat, err := os.Stat(path); err == nil && stat.IsDir() { + pkgs, err := parser.ParseDir(fs, path, nil, 0) + if err != nil { + fmt.Printf("parsing dir '%s': %s", path, err) + } + for name, pkg := range pkgs { + log.Println("Found package:", name) + + fset := make([]*ast.File, len(pkg.Files), len(pkg.Files)) + idx := 0 + for _, value := range pkg.Files { + fset[idx] = value + idx++ + } + + if err := PrintDefsUses(name, fs, fset); err != nil { + log.Print(err) // type error + } + } + } else { + + fset, err := parser.ParseFile(fs, path, nil, 0) + + if err != nil { + fmt.Printf("parsing file '%s': %s", path, err) + } + name := fset.Name.String() + if err := PrintDefsUses(name, fs, []*ast.File{fset}); err != nil { + log.Print(err) // type error + } + } +} |