blob: 0e2bdcde9ad47cbb25fa0679ef59e4ac921493a7 [file] [log] [blame]
{{/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/}}
{{Global "module" ""}}
{{Include "rpc_common_go.tmpl"}}
{{$api := Global "API"}}
{{$ | Macro "Rpc" "role" "" "api" | GoFmt | Write (print $api "_rpc.go")}}
{{$ | Macro "Rpc" "role" "Extra" "api" | GoFmt | Write (print $api "_extra.go")}}
{{$ | Macro "Rpc" "role" "Helpers" "api" | GoFmt | Write (print $api "_helpers.go")}}
{{$ | Macro "Client" | GoFmt | Write (print $api "_client.go")}}
{{$ | Macro "Server" | GoFmt | Write (print $api "_server.go")}}
{{define "Rpc"}}
{{template "GeneratedHeader"}}
{{Macro (print "Imports" $.role) $.api}}
{{range $i, $c := $.api.Functions}}
{{Macro (print "Call" $.role) $c}}
{{Macro (print "Result" $.role) $c}}
{{end}}
{{range $_, $h := $.api.Pseudonyms}}
{{if GetAnnotation $h "handle"}}
{{Macro (print "Handle" $.role) $h}}
{{end}}
{{end}}
{{range $_, $a := $.api.Slices}}
{{Macro (print "Array" $.role) $a}}
{{end}}
{{range $_, $e := $.api.Enums}}
{{Macro (print "Enum" $.role) $e}}
{{end}}
{{range $i, $c := $.api.Classes}}
{{if GetAnnotation $c "Interface"}}
{{Macro (print "Interface" $.role) $c}}¶
{{end}}
{{end}}
{{range $i, $c := $.api.Classes}}
{{if not (GetAnnotation $c "Interface")}}
{{Macro (print "Class" $.role) $c}}¶
{{end}}
{{end}}
{{end}}
{{define "Imports"}}
package {{Global "OutputDir"}};
import (
"android.googlesource.com/platform/tools/gpu/binary"
"android.googlesource.com/platform/tools/gpu/log"
)
type RPC interface {
{{range $_, $c := $.Functions}}
{{Macro "RpcInterfaceMethod" $c}}
{{end}}
}
{{end}}
{{define "ImportsExtra"}}
package {{Global "OutputDir"}};
{{end}}
{{define "ImportsHelpers"}}
package {{Global "OutputDir"}};
import (
"fmt"
"android.googlesource.com/platform/tools/gpu/binary"
)
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the interface method declaration for a single RPC command.
-------------------------------------------------------------------------------
*/}}
{{define "RpcInterfaceMethod"}}
{{AssertType $ "Function"}}
{{Macro "VerifyInterfaceReturnTypeIsRef" $}}
{{$.Name}}(l log.Logger, {{Macro "Parameters" $}})§
({{if not (IsVoid $.Return.Type)}}{{Macro "Type" $.Return.Type}}, {{end}}error)
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a comma-separated list of command parameters (name followed by type).
-------------------------------------------------------------------------------
*/}}
{{define "Parameters"}}
{{AssertType $ "Function"}}
{{range $i, $p := $.CallParameters}}
{{if $i}},{{end}}§
{{Macro "Parameter" "Parameter" $p "Command" $}}§
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a comma-separated list of command arguments (names).
-------------------------------------------------------------------------------
*/}}
{{define "Arguments"}}
{{AssertType $ "Function"}}
{{range $i, $p := $.CallParameters}}{{if $i}}, {{end}}§{{$p.Name}}:{{$p.Name}}{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a single command parameter (name followed by type).
-------------------------------------------------------------------------------
*/}}
{{define "Parameter"}}
{{AssertType $.Parameter "Parameter"}}
{{AssertType $.Command "Function"}}
{{Macro "VerifyInterfaceParameterIsRef" "Parameter" $.Parameter "Command" $.Command}}
{{$.Parameter.Name}} {{Macro "Type" (TypeOf $.Parameter)}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Walks a class hierarchy to visit all the fields, calling the specified macro
for each field.
-------------------------------------------------------------------------------
*/}}
{{define "AllFields"}}
{{AssertType $.Class "Class"}}
{{AssertType $.Macro "string"}}
{{Macro "TraverseFields" "Impl" $.Class "Class" $.Class "Macro" $.Macro}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Walks a class hierarchy to visit all the fields, calling the specified macro
for each field.
-------------------------------------------------------------------------------
*/}}
{{define "TraverseFields"}}
{{AssertType $.Impl "Class"}}
{{AssertType $.Class "Class"}}
{{AssertType $.Macro "string"}}
{{range $_, $e := $.Class.Extends}}
{{Macro "TraverseFields" "Impl" $.Impl "Class" $e "Macro" $.Macro}}
{{end}}
{{range $_, $f := $.Class.Fields}}
{{Macro $.Macro "Impl" $.Impl "Class" $.Class "Field" $f}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Declares a single field accessor (getter) of an interface.
-------------------------------------------------------------------------------
*/}}
{{define "DeclareInterfaceFieldAccessor"}}
{{AssertType $.Field "Field"}}
Get{{$.Field.Name}}() {{Macro "Type" (TypeOf $.Field)}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Declares a single class field.
-------------------------------------------------------------------------------
*/}}
{{define "DeclareClassField"}}
{{AssertType $.Field "Field"}}
{{$.Field.Name}} {{Macro "Type" (TypeOf $.Field)}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a single field parameter name-type pair for the constructor of a class.
-------------------------------------------------------------------------------
*/}}
{{define "CreateClassParameter"}}
{{AssertType $.Field "Field"}}
{{$.Field.Name}} {{Macro "Type" (TypeOf $.Field)}},
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a the initializer for a single class field.
-------------------------------------------------------------------------------
*/}}
{{define "AssignClassParameter"}}
{{AssertType $.Field "Field"}}
{{$.Field.Name}}: {{$.Field.Name}},
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits a single field accessor (getter) for a concrete class.
-------------------------------------------------------------------------------
*/}}
{{define "DefineClassFieldAccessor"}}
{{AssertType $.Field "Field"}}
{{AssertType $.Impl "Class"}}
func (c *{{$.Impl.Name}}) Get{{$.Field.Name}}() {{Macro "Type" (TypeOf $.Field)}} { return c.{{$.Field.Name}} }
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the interface of a class annotated with @Interface.
-------------------------------------------------------------------------------
*/}}
{{define "Interface"}}
{{AssertType $ "Class"}}
{{$iname := $.Name}}
// Interface {{$.Name}}
type {{$iname}} interface {
{{if eq (len $.Extends) 0}}
binary.Object
{{end}}
{{Macro "AllFields" "Class" $ "Macro" "DeclareInterfaceFieldAccessor"}}
}
{{end}}
{{define "InterfaceExtra"}}{{end}}
{{define "InterfaceHelpers"}}{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the implementation of a class.
-------------------------------------------------------------------------------
*/}}
{{define "Class"}}
{{AssertType $ "Class"}}
{{Macro "AllFields" "Class" $ "Macro" "VerifyInterfaceFieldIsRef"}}
// Class {{$.Name}}
type {{$.Name}} struct {
binary.Generate
{{Macro "AllFields" "Class" $ "Macro" "DeclareClassField"}}
}
{{end}}
{{define "ClassExtra"}}{{end}}
{{define "ClassHelpers"}}
func Create{{$.Name}}(
{{Macro "AllFields" "Class" $ "Macro" "CreateClassParameter"}}
) *{{$.Name}} {
return &{{$.Name}} {
{{Macro "AllFields" "Class" $ "Macro" "AssignClassParameter"}}
}
}
{{Macro "AllFields" "Class" $ "Macro" "DefineClassFieldAccessor"}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the encoder of a handle.
-------------------------------------------------------------------------------
*/}}
{{define "Handle"}}
{{AssertType $ "Pseudonym"}}
// Handle {{$.Name}}
type {{$.Name}} struct {
binary.Generate
ID binary.ID
}
{{end}}
{{define "HandleExtra"}}{{end}}
{{define "HandleHelpers"}}
func (h {{$.Name}}) Valid() bool {
return h.ID.Valid()
}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the definition of an array.
-------------------------------------------------------------------------------
*/}}
{{define "Array"}}
{{AssertType $ "Slice"}}
// Array {{$.Name}}
type {{Macro "Type" $}} []{{Macro "Type" $.To}}
{{end}}
{{define "ArrayExtra"}}
{{AssertType $ "Slice"}}
{{end}}
{{define "ArrayHelpers"}}
{{AssertType $ "Slice"}}
func (a {{Macro "Type" $}}) Format(f fmt.State, c rune) {
fmt.Fprintf(f, "[%d]{{$.Name}}", len(a))
}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the definition of an enum.
-------------------------------------------------------------------------------
*/}}
{{define "Enum"}}
{{AssertType $ "Enum"}}
// Enum {{$.Name}}
type {{$.Name}} int
const (
{{range $_, $e := $.Entries}}
{{$.Name}}{{$e.Name}} {{$.Name}}= {{$e.Value}}
{{end}}
)
{{end}}
{{define "EnumExtra"}}
{{AssertType $ "Enum"}}
{{end}}
{{define "EnumHelpers"}}
{{AssertType $ "Enum"}}
{{range $_, $e := $.Entries}}
func (i {{$.Name}}) Is{{$e.Name}}() bool { return i == {{$.Name}}{{$e.Name}} }
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the name of the call type for a single command.
-------------------------------------------------------------------------------
*/}}
{{define "CallName"}}
{{AssertType $ "Function"}}
{{print "call" $.Name}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the name of the result type for a single command.
-------------------------------------------------------------------------------
*/}}
{{define "ResultName"}}
{{AssertType $ "Function"}}
{{print "result" $.Name}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the call structure for a single command.
-------------------------------------------------------------------------------
*/}}
{{define "Call"}}
{{AssertType $ "Function"}}
{{end}}
{{define "CallExtra"}}
{{AssertType $ "Function"}}
// Call {{$.Name}}
type {{Macro "CallName" $}} struct {
binary.Generate
{{range $i, $p := $.CallParameters}}
{{$p.Name}} {{Macro "Type" (TypeOf $p)}}
{{end}}
}
{{end}}
{{define "CallHelpers"}}
{{AssertType $ "Function"}}
func (c {{Macro "CallName" $}}) Format(f fmt.State, r rune) {
fmt.Fprintf(f, "{{$.Name}}(§
{{range $i, $p := $.CallParameters}}{{if $i}}, {{end}}{{$p.Name}}: %v{{end}})",
{{range $i, $p := $.CallParameters}}c.{{$p.Name}},{{end}}
)
}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the result structure for a single command.
-------------------------------------------------------------------------------
*/}}
{{define "Result"}}
{{AssertType $ "Function"}}
{{end}}
{{define "ResultExtra"}}
{{AssertType $ "Function"}}
// Result {{$.Name}}
type {{Macro "ResultName" $}} struct {
binary.Generate
{{if not (IsVoid $.Return.Type)}}
value {{Macro "Type" $.Return.Type}}
{{end}}
}
{{end}}
{{define "ResultHelpers"}}
{{AssertType $ "Function"}}
func (r {{Macro "ResultName" $}}) Format(f fmt.State, c rune) {
{{if not (IsVoid $.Return.Type)}}
fmt.Fprintf(f, "res: %#v", r.value)
{{else}}
fmt.Fprintf(f, "void")
{{end}}
}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the RPC client implementation
-------------------------------------------------------------------------------
*/}}
{{define "Client"}}
{{AssertType $ "API"}}
{{template "GeneratedHeader"}}
package {{Global "OutputDir"}};
import (
"io"
"android.googlesource.com/platform/tools/gpu/log"
"android.googlesource.com/platform/tools/gpu/rpc"
)
type client struct {
rpc.Client
}
func CreateClient(r io.Reader, w io.Writer, mtu int) RPC {
return client{rpc.NewClient(r, w, mtu)}
}
// Client compliance
{{range $_, $c := $.Functions}}
{{if not (IsVoid $c.Return.Type)}}
func (c client) {{$c.Name}}(l log.Logger, {{Macro "Parameters" $c}}) (res {{Macro "Type" $c.Return.Type}}, err error) {
var val interface{}
if val, err = c.Send(&{{Macro "CallName" $c}}{ {{Macro "Arguments" $c}} }); err == nil {
res = val.(*{{Macro "ResultName" $c}}).value
} else {
l.Errorf("RPC {{$c.Name}} failed with error: %v", err)
}
return
}
{{else}}
func (c client) {{$c.Name}}(l log.Logger, {{Macro "Parameters" $c}}) error {
_, err := c.Send(&{{Macro "CallName" $c}}{ {{Macro "Arguments" $c}} })
return err
}
{{end}}
{{end}}
{{end}}
{{/*
-------------------------------------------------------------------------------
Emits the RPC server implementation
-------------------------------------------------------------------------------
*/}}
{{define "Server"}}
{{AssertType $ "API"}}
{{template "GeneratedHeader"}}
package {{Global "OutputDir"}};
import (
"fmt"
"io"
"runtime/debug"
"android.googlesource.com/platform/tools/gpu/log"
"android.googlesource.com/platform/tools/gpu/rpc"
)
func BindServer(r io.Reader, w io.Writer, mtu int, l log.Logger, server RPC) {
rpc.Serve(l, r, w, mtu, func(in interface{}) (res binary.Object) {
l := l.Fork().Enter(fmt.Sprintf("%v", in))
defer func() {
if err := recover(); err == nil {
l.Infof("↪ %v", res)
} else {
msg := fmt.Sprintf("Panic: %v\n%v", err, string(debug.Stack()))
l.Errorf(msg)
res = rpc.NewError(msg)
}
}()
switch call := in.(type) {
{{range $i, $c := $.Functions}}
case *{{Macro "CallName" $c}}:
{{if not (IsVoid $c.Return.Type)}}
if res, err := server.{{$c.Name}}(l{{range $p := $c.CallParameters}}, call.{{$p.Name}}{{end}}); err == nil {
return &{{Macro "ResultName" $c}}{ value:res }
} else {
return rpc.NewError(err.Error())
}
{{else}}
if err := server.{{$c.Name}}(l{{range $p := $c.CallParameters}}, call.{{$p.Name}}{{end}}); err == nil {
return &{{Macro "ResultName" $c}}{}
} else {
return rpc.NewError(err.Error())
}
{{end}}
{{end}}
default:
return rpc.NewError("Unexpected RPC function: %T", call)
}
})
}
{{end}}