Created
January 8, 2021 23:19
-
-
Save ianloic/142138a2dc318de8ec1b3705666b0aab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type piece interface { | |
Write(wr io.Writer) | |
} | |
type stringPiece string | |
func (sp stringPiece) Write(wr io.Writer) { | |
fmt.Fprint(wr, string(sp)) | |
} | |
type Argument struct { | |
Type string | |
Name string | |
} | |
type Func struct { | |
virtual bool | |
explicit bool | |
Return string | |
Name string | |
args []Argument | |
override bool | |
body *Scope | |
equals string | |
} | |
func (f *Func) Write(wr io.Writer) { | |
var args []string = nil | |
for _, arg := range f.args { | |
args = append(args, fmt.Sprintf("%s %s", arg.Type, arg.Name)) | |
} | |
if f.explicit { | |
fmt.Fprint(wr, "explicit ") | |
} | |
if f.virtual { | |
fmt.Fprint(wr, "virtual ") | |
} | |
fmt.Fprintf(wr, "%s %s(%s)", f.Return, f.Name, strings.Join(args, ", ")) | |
if f.override { | |
fmt.Fprint(wr, " override") | |
} | |
if f.body == nil { | |
if f.equals != "" { | |
fmt.Fprintf(wr, " = %s", f.equals) | |
} | |
fmt.Fprintln(wr, ";") | |
} else { | |
fmt.Fprintln(wr, " {") | |
f.body.Write(wr) | |
fmt.Fprintln(wr, "}") | |
} | |
} | |
func (f *Func) Type() string { | |
var args []string = nil | |
for _, arg := range f.args { | |
args = append(args, arg.Type) | |
} | |
return fmt.Sprintf("%s(%s)", f.Return, strings.Join(args, ", ")) | |
} | |
func (f *Func) Argument(t string, n string) *Func { | |
f.args = append(f.args, Argument{t, n}) | |
return f | |
} | |
func (f *Func) Arguments(args []Argument) *Func { | |
f.args = append(f.args, args...) | |
return f | |
} | |
func (f *Func) Virtual() *Func { | |
f.virtual = true | |
return f | |
} | |
func (f *Func) Explicit() *Func { | |
f.explicit = true | |
return f | |
} | |
func (f *Func) Override() *Func { | |
f.override = true | |
return f | |
} | |
func (f *Func) PureVirtual() { | |
f.Virtual().equals = "0" | |
} | |
func (f *Func) Default() { | |
f.equals = "default" | |
} | |
func (f *Func) Delete() { | |
f.equals = "delete" | |
} | |
func (f *Func) Body(b func(s *Scope)) { | |
f.body = &Scope{} | |
b(f.body) | |
} | |
type Class struct { | |
Name string | |
final bool | |
extends []string | |
body *Scope | |
} | |
func (c *Class) Write(wr io.Writer) { | |
fmt.Fprintf(wr, "class %s", c.Name) | |
if c.final { | |
fmt.Fprint(wr, " final") | |
} | |
if c.extends != nil { | |
fmt.Fprintf(wr, " : %s", strings.Join(c.extends, ", ")) | |
} | |
if c.body != nil { | |
fmt.Fprintln(wr, " {") | |
c.body.Write(wr) | |
fmt.Fprint(wr, "}") | |
} | |
fmt.Fprintln(wr, ";") | |
} | |
func (c *Class) Final() *Class { | |
c.final = true | |
return c | |
} | |
func (c *Class) Extend(visibility string, class string) *Class { | |
c.extends = append(c.extends, fmt.Sprint(visibility, class)) | |
return c | |
} | |
func (c *Class) visibility(v string, f func(cs *ClassScope)) *Class { | |
if c.body == nil { | |
c.body = &Scope{} | |
} | |
cs := &ClassScope{&Scope{}, c} | |
c.body.add(cs) | |
cs.printf("%s:\n", v) | |
f(cs) | |
return c | |
} | |
// Public defines public members in a class | |
func (c *Class) Public(f func(cs *ClassScope)) *Class { | |
return c.visibility("public", f) | |
} | |
// Private defines public members in a class | |
func (c *Class) Private(f func(cs *ClassScope)) *Class { | |
return c.visibility("private", f) | |
} | |
type ClassScope struct { | |
*Scope | |
class *Class | |
} | |
func (cs *ClassScope) Ctor() *Func { | |
return cs.Func("", cs.class.Name) | |
} | |
func (cs *ClassScope) CopyCtor() *Func { | |
return cs.Ctor().Argument("const "+cs.class.Name+"&", "other") | |
} | |
func (cs *ClassScope) Dtor() *Func { | |
return cs.Func("", "~"+cs.class.Name) | |
} | |
func (cs *ClassScope) CopyOperator() *Func { | |
return cs.Func(cs.class.Name+"&", "operator=").Argument("const "+cs.class.Name+"&", "other") | |
} | |
func (cs *ClassScope) Friend(f string) { | |
cs.printf("friend %s;\n", f) | |
} | |
type Var struct { | |
typ string | |
name string | |
value string | |
} | |
func (v *Var) Write(wr io.Writer) { | |
fmt.Fprintf(wr, "%s %s", v.typ, v.name) | |
if v.value != "" { | |
fmt.Fprint(wr, " = %s", v.value) | |
} | |
fmt.Fprintln(wr, ";") | |
} | |
func (v *Var) Value(value string) { | |
v.value = value | |
} | |
type Scope struct { | |
pieces []piece | |
} | |
func (s *Scope) Write(wr io.Writer) { | |
for _, p := range s.pieces { | |
p.Write(wr) | |
} | |
} | |
func (s *Scope) add(piece piece) { | |
s.pieces = append(s.pieces, piece) | |
} | |
func (s *Scope) printf(format string, a ...interface{}) { | |
s.add(stringPiece(fmt.Sprintf(format, a...))) | |
} | |
func (s *Scope) println(line string) { | |
s.add(stringPiece(fmt.Sprintln(line))) | |
} | |
func (s *Scope) DocComments(a fidl.Attributes) { | |
for _, c := range a.DocComments() { | |
s.printf("///%s\n", c) | |
} | |
} | |
func (s *Scope) Using(new string, old string) { | |
s.printf("using %s = %s;\n", new, old) | |
} | |
func (s *Scope) Typedef(old string, new string) { | |
s.printf("typedef %s %s;\n", old, new) | |
} | |
func (s *Scope) Class(name string) *Class { | |
c := &Class{Name: name} | |
s.add(c) | |
return c | |
} | |
func (s *Scope) Var(t string, name string) *Var { | |
v := &Var{typ: t, name: name} | |
s.add(v) | |
return v | |
} | |
func (s *Scope) VarDecl(t string, name string) { | |
s.printf("%s %s;\n", t, name) | |
} | |
func (s *Scope) Func(ret string, name string) *Func { | |
f := &Func{Return: ret, Name: name} | |
s.add(f) | |
return f | |
} | |
func (s *Scope) IfdefFuchsia(f func(*Scope)) { | |
s.println("#ifdef __Fuchsia__") | |
f(s) | |
s.println("#endif // __Fuchsia__\n") | |
} | |
func (s *Scope) Namespace(name string, f func(*Scope)) { | |
s.printf("namespace %s {\n", name) | |
f(s) | |
s.printf("} // namespace %s\n\n", name) | |
} | |
func protocolForwardDeclaration(s *Scope, protocol *cpp.Protocol) { | |
s.IfdefFuchsia(func(s *Scope) { | |
s.DocComments(protocol.Attributes) | |
s.Using(fmt.Sprintf("%sPtr", protocol.Name), | |
fmt.Sprintf("::fidl::InterfacePtr<%s>", protocol.Name)) | |
s.Class(protocol.ProxyName) | |
s.Class(protocol.StubName) | |
s.Class(protocol.EventSenderName) | |
s.Class(protocol.SyncName) | |
s.Using(fmt.Sprintf("%sSyncPtr", protocol.Name), | |
fmt.Sprintf("::fidl::SynchronousInterfacePtr<%s>", protocol.Name)) | |
s.Class(protocol.SyncProxyName) | |
s.Namespace("internal", func(s *Scope) { | |
for _, method := range protocol.Methods { | |
s.Var("constexpr uint64_t", method.OrdinalName).Value(fmt.Sprintf("0x%Xlu", method.Ordinal)) | |
} | |
}) | |
}) | |
} | |
func paramTypes(params []cpp.Parameter) string { | |
var types []string | |
for _, param := range params { | |
types = append(types, param.Type.FullDecl) | |
} | |
return strings.Join(types, ", ") | |
} | |
func argsFromParams(params []cpp.Parameter) []Argument { | |
var args []Argument | |
for _, param := range params { | |
args = append(args, Argument{ | |
Name: param.Name, | |
Type: param.Type.FullDecl, | |
}) | |
} | |
return args | |
} | |
// This should be defined on cpp.Method | |
func requestMethodFunc(s *ClassScope, m *cpp.Method) *Func { | |
f := s.Func("void", m.Name).Virtual().Arguments(argsFromParams(m.Request)) | |
if m.HasResponse { | |
f.Argument(m.CallbackType, "callback") | |
} | |
return f | |
} | |
// This should be defined on cpp.Method | |
func responseMethodFunc(s *ClassScope, m *cpp.Method) *Func { | |
return s.Func("void", m.Name).Virtual().Arguments(argsFromParams(m.Request)) | |
} | |
// This should be defined on cpp.Method | |
func syncMethodFunc(s *ClassScope, m *cpp.Method) *Func { | |
f := s.Func("zx_status_t", m.Name).Virtual().Arguments(argsFromParams(m.Request)) | |
if m.HasResponse { | |
for _, arg := range m.Response { | |
f.Argument(arg.Type.FullDecl+"*", "out_"+arg.Name) | |
} | |
} | |
return f | |
} | |
func protocolDeclaration(s *Scope, protocol *cpp.Protocol) { | |
s.IfdefFuchsia(func(s *Scope) { | |
// Interface class | |
s.DocComments(protocol.Attributes) | |
s.Class(protocol.Name). | |
Public(func(s *ClassScope) { | |
s.Using("Proxy_", protocol.ProxyName) | |
s.Using("Stub_", protocol.StubName) | |
s.Using("EventSender_", protocol.EventSenderName) | |
s.Using("Sync_", protocol.SyncName) | |
if protocol.ServiceName != "" { | |
s.Var("static const char", "Name_[]") | |
} | |
s.Dtor().Virtual() | |
for _, method := range protocol.Methods { | |
if method.HasResponse { | |
s.Using(method.CallbackType, | |
fmt.Sprintf("%s<void(%s)>", method.CallbackWrapper(), paramTypes(method.Response))) | |
} | |
if method.HasRequest { | |
s.DocComments(method.Attributes) | |
f := requestMethodFunc(s, &method) | |
if method.Transitional { | |
f.Body(func(s *Scope) {}) | |
} else { | |
f.PureVirtual() | |
} | |
} | |
} | |
}) | |
// Request decoder class | |
s.Class(protocol.RequestDecoderName). | |
Public(func(s *ClassScope) { | |
s.Ctor().Default() | |
s.Dtor().Virtual().Default() | |
s.Func("static const fidl_type_t*", "GetType"). | |
Argument("uint64_t", "ordinal"). | |
Argument("bool*", "out_needs_response") | |
for _, method := range protocol.Methods { | |
if method.HasRequest { | |
requestMethodFunc(s, &method) | |
} | |
} | |
}) | |
// Response decoder class | |
s.Class(protocol.ResponseDecoderName).Public(func(s *ClassScope) { | |
s.Ctor().Default() | |
s.Dtor().Virtual().Default() | |
s.Func("static const fidl_type_t*", "GetType").Argument("uint64_t", "ordinal") | |
for _, method := range protocol.Methods { | |
if method.HasResponse { | |
responseMethodFunc(s, &method) | |
} | |
} | |
}) | |
// Event sender class | |
s.Class(protocol.EventSenderName).Public(func(s *ClassScope) { | |
s.Ctor() | |
for _, method := range protocol.Methods { | |
if !method.HasRequest && method.HasResponse { | |
responseMethodFunc(s, &method).PureVirtual() | |
} | |
} | |
}) | |
// Sync interface class | |
s.Class(protocol.SyncName).Public(func(s *ClassScope) { | |
s.Using("Proxy_", protocol.SyncProxyName) | |
s.Dtor().Virtual() | |
for _, method := range protocol.Methods { | |
if method.HasRequest { | |
syncMethodFunc(s, &method).PureVirtual() | |
} | |
} | |
}) | |
// Proxy class | |
s.Class(protocol.ProxyName).Final(). | |
Extend("public", "::fidl::internal::Proxy"). | |
Extend("public", protocol.Name). | |
Public(func(s *ClassScope) { | |
s.Ctor().Explicit().Argument("::fidl::internal::ProxyController*", "controller") | |
s.Dtor().Override() | |
s.Func("zx_status_t", "Dispatch_"). | |
Argument("::fidl::HLCPPIncomingMessage", "message"). | |
Override() | |
for _, method := range protocol.Methods { | |
if method.HasRequest { | |
requestMethodFunc(s, &method).Override() | |
} else { | |
if method.HasResponse { | |
s.Var(method.CallbackType, method.Name) | |
} | |
} | |
} | |
}). | |
Private(func(s *ClassScope) { | |
s.CopyCtor().Delete() | |
s.CopyOperator().Delete() | |
}) | |
// Stub class | |
s.Class(protocol.StubName).Final(). | |
Extend("public", "::fidl::internal::Stub"). | |
Extend("public", protocol.EventSenderName). | |
Public(func(s *ClassScope) { | |
s.Typedef(fmt.Sprintf("class %s::%s", protocol.Namespace, protocol.Name), protocol.ClassName) | |
s.Ctor().Explicit().Argument(protocol.ClassName+"*", "impl") | |
s.Dtor().Override() | |
s.Func("zx_status_t", "Dispatch_"). | |
Argument("::fidl::HLCPPIncomingMessage", "message"). | |
Argument("::fidl::internal::PendingResponse", "response"). | |
Override() | |
for _, method := range protocol.Methods { | |
if !method.HasRequest && method.HasResponse { | |
responseMethodFunc(s, &method).Override() | |
} | |
} | |
}). | |
Private(func(s *ClassScope) { | |
s.Var(protocol.ClassName+"*", "impl_") | |
}) | |
// Sync proxy class | |
s.Class(protocol.SyncProxyName). | |
Extend("public", protocol.SyncName). | |
Public(func(s *ClassScope) { | |
s.Ctor().Explicit().Argument("::zx::channel", "channel") | |
s.Dtor().Override() | |
for _, method := range protocol.Methods { | |
if method.HasRequest { | |
syncMethodFunc(s, &method).Override() | |
} | |
} | |
}). | |
Private(func(s *ClassScope) { | |
s.Var("::fidl::internal::SynchronousProxy", "proxy_") | |
s.Friend("class ::fidl::SynchronousInterfacePtr<" + protocol.Name + ">") | |
}) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const protocolTemplateProxiesAndStubs = ` | |
{{- define "ProtocolForwardDeclaration/ProxiesAndStubs" }} | |
#ifdef __Fuchsia__ | |
{{- range .DocComments }} | |
///{{ . }} | |
{{- end }} | |
using {{ .Name }}Ptr = ::fidl::InterfacePtr<{{ .Name }}>; | |
class {{ .ProxyName }}; | |
class {{ .StubName }}; | |
class {{ .EventSenderName }}; | |
class {{ .SyncName }}; | |
using {{ .Name }}SyncPtr = ::fidl::SynchronousInterfacePtr<{{ .Name }}>; | |
class {{ .SyncProxyName }}; | |
namespace internal { | |
{{- range .Methods }} | |
constexpr uint64_t {{ .OrdinalName }} = {{ .Ordinal | printf "%#x" }}lu; | |
{{- end }} | |
} // namespace | |
#endif // __Fuchsia__ | |
{{- end }} | |
{{- define "Params" -}} | |
{{- range $index, $param := . -}} | |
{{- if $index }}, {{ end -}}{{ $param.Type.FullDecl }} {{ $param.Name }} | |
{{- end -}} | |
{{ end }} | |
{{- define "OutParams" -}} | |
{{- range $index, $param := . -}} | |
{{- if $index }}, {{ end -}}{{ $param.Type.FullDecl }}* out_{{ $param.Name }} | |
{{- end -}} | |
{{ end }} | |
{{- define "ParamTypes" -}} | |
{{- range $index, $param := . -}} | |
{{- if $index }}, {{ end -}}{{ $param.Type.FullDecl }} | |
{{- end -}} | |
{{ end }} | |
{{- define "RequestMethodSignature" -}} | |
{{- if .HasResponse -}} | |
{{ .Name }}({{ template "Params" .Request }}{{ if .Request }}, {{ end }}{{ .CallbackType }} callback) | |
{{- else -}} | |
{{ .Name }}({{ template "Params" .Request }}) | |
{{- end -}} | |
{{ end -}} | |
{{- define "EventMethodSignature" -}} | |
{{ .Name }}({{ template "Params" .Response }}) | |
{{- end -}} | |
{{- define "SyncRequestMethodSignature" -}} | |
{{- if .Response -}} | |
{{ .Name }}({{ template "Params" .Request }}{{ if .Request }}, {{ end }}{{ template "OutParams" .Response }}) | |
{{- else -}} | |
{{ .Name }}({{ template "Params" .Request }}) | |
{{- end -}} | |
{{ end -}} | |
{{- define "ProtocolDeclaration/ProxiesAndStubs" }} | |
#ifdef __Fuchsia__ | |
{{- range .DocComments }} | |
///{{ . }} | |
{{- end }} | |
class {{ .Name }} { | |
public: | |
using Proxy_ = {{ .ProxyName }}; | |
using Stub_ = {{ .StubName }}; | |
using EventSender_ = {{ .EventSenderName }}; | |
using Sync_ = {{ .SyncName }}; | |
{{- if .ServiceName }} | |
static const char Name_[]; | |
{{- end }} | |
virtual ~{{ .Name }}(); | |
{{- range .Methods }} | |
{{- if .HasResponse }} | |
using {{ .CallbackType }} = | |
{{ .CallbackWrapper }}<void({{ template "ParamTypes" .Response }})>; | |
{{- end }} | |
{{- if .HasRequest }} | |
{{ range .DocComments }} | |
///{{ . }} | |
{{- end }} | |
{{- if .Transitional }} | |
virtual void {{ template "RequestMethodSignature" . }} { } | |
{{- else }} | |
virtual void {{ template "RequestMethodSignature" . }} = 0; | |
{{- end }} | |
{{- end }} | |
{{- end }} | |
}; | |
class {{ .RequestDecoderName }} { | |
public: | |
{{ .RequestDecoderName }}() = default; | |
virtual ~{{ .RequestDecoderName }}() = default; | |
static const fidl_type_t* GetType(uint64_t ordinal, bool* out_needs_response); | |
{{- range .Methods }} | |
{{- if .HasRequest }} | |
virtual void {{ .Name }}({{ template "Params" .Request }}) = 0; | |
{{- end }} | |
{{- end }} | |
}; | |
class {{ .ResponseDecoderName }} { | |
public: | |
{{ .ResponseDecoderName }}() = default; | |
virtual ~{{ .ResponseDecoderName }}() = default; | |
static const fidl_type_t* GetType(uint64_t ordinal); | |
{{- range .Methods }} | |
{{- if .HasResponse }} | |
virtual void {{ .Name }}({{ template "Params" .Response }}) = 0; | |
{{- end }} | |
{{- end }} | |
}; | |
class {{ .EventSenderName }} { | |
public: | |
virtual ~{{ .EventSenderName }}(); | |
{{- range .Methods }} | |
{{- if not .HasRequest }} | |
{{- if .HasResponse }} | |
virtual void {{ template "EventMethodSignature" . }} = 0; | |
{{- end }} | |
{{- end }} | |
{{- end }} | |
}; | |
class {{ .SyncName }} { | |
public: | |
using Proxy_ = {{ .SyncProxyName }}; | |
virtual ~{{ .SyncName }}(); | |
{{- range .Methods }} | |
{{- if .HasRequest }} | |
virtual zx_status_t {{ template "SyncRequestMethodSignature" . }} = 0; | |
{{- end }} | |
{{- end }} | |
}; | |
class {{ .ProxyName }} final : public ::fidl::internal::Proxy, public {{ .Name }} { | |
public: | |
explicit {{ .ProxyName }}(::fidl::internal::ProxyController* controller); | |
~{{ .ProxyName }}() override; | |
zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message) override; | |
{{- range .Methods }} | |
{{- if .HasRequest }} | |
void {{ template "RequestMethodSignature" . }} override; | |
{{- else if .HasResponse }} | |
{{ .CallbackType }} {{ .Name }}; | |
{{- end }} | |
{{- end }} | |
private: | |
{{ .ProxyName }}(const {{ .ProxyName }}&) = delete; | |
{{ .ProxyName }}& operator=(const {{ .ProxyName }}&) = delete; | |
::fidl::internal::ProxyController* controller_; | |
}; | |
class {{ .StubName }} final : public ::fidl::internal::Stub, public {{ .EventSenderName }} { | |
public: | |
typedef class {{ .Namespace }}::{{ .Name }} {{ .ClassName }}; | |
explicit {{ .StubName }}({{ .ClassName }}* impl); | |
~{{ .StubName }}() override; | |
zx_status_t Dispatch_(::fidl::HLCPPIncomingMessage message, | |
::fidl::internal::PendingResponse response) override; | |
{{- range .Methods }} | |
{{- if not .HasRequest }} | |
{{- if .HasResponse }} | |
void {{ template "EventMethodSignature" . }} override; | |
{{- end }} | |
{{- end }} | |
{{- end }} | |
private: | |
{{ .ClassName }}* impl_; | |
}; | |
class {{ .SyncProxyName }} : public {{ .SyncName }} { | |
public: | |
explicit {{ .SyncProxyName }}(::zx::channel channel); | |
~{{ .SyncProxyName }}() override; | |
{{- range .Methods }} | |
{{- if .HasRequest }} | |
zx_status_t {{ template "SyncRequestMethodSignature" . }} override; | |
{{- end }} | |
{{- end }} | |
private: | |
::fidl::internal::SynchronousProxy proxy_; | |
friend class ::fidl::SynchronousInterfacePtr<{{ .Name }}>; | |
}; | |
#endif // __Fuchsia__ | |
{{- end }} | |
` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment