blob: f02571516bea9eda2503f00e7f6dc2895d20987e [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{% import "struct.tmpl" as struct_macros %}
{% import "runtime_type_macros.tmpl" as runtime_type_macros %}
{%- macro declare_params(struct) %}
{%- for field in struct.fields -%}
{{field|name(False)}} {{field.kind|go_type}}{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}
{% macro declare_request_params(method) %}
({{declare_params(method.param_struct)}})
{%- if method.response_parameters|is_none_or_empty -%}
{{' (err error)'}}
{%- else -%}
{{' '}}({{declare_params(method.response_param_struct)}}, err error)
{%- endif -%}
{% endmacro %}
{%- macro flags(method, is_response) -%}
{%- if not method|has_response -%}
bindings.MessageNoFlag
{%- elif is_response: -%}
bindings.MessageIsResponseFlag
{%- else -%}
bindings.MessageExpectsResponseFlag
{%- endif -%}
{%- endmacro -%}
{% macro define(interface, descpkg, typepkg, pkg) %}
type {{interface|name}} interface {
{% for method in interface.methods %}
{{method|name}}{{declare_request_params(method)}}
{% endfor %}
}
{{runtime_type_macros.maybeWriteStaticMojomTypeAccessor(typepkg, interface)}}
{% if interface.service_name %}
var {{interface|name(False)}}_Name = "{{interface.service_name}}"
{% endif %}
type {{interface|name}}_Request bindings.InterfaceRequest
{% if interface.service_name %}
func (r *{{interface|name}}_Request) Name() string {
return {{interface|name(False)}}_Name
}
{% endif %}
{%- set type_name = interface|name + '_Request' %}
{{runtime_type_macros.maybeWriteMojomTypeAccessor(typepkg, interface, type_name)}}
type {{interface|name}}_Pointer bindings.InterfacePointer
{% if interface.service_name %}
func (p *{{interface|name}}_Pointer) Name() string {
return {{interface|name(False)}}_Name
}
{% endif %}
type {{interface|name}}_ServiceFactory struct{
Delegate {{interface|name}}_Factory
}
type {{interface|name}}_Factory interface {
Create(request {{interface|name}}_Request)
}
{% if interface.service_name %}
func (f *{{interface|name}}_ServiceFactory) Name() string {
return {{interface|name(False)}}_Name
}
{% endif %}
// TODO(rudominer) This should only be defined for top-level interfaces.
func (f *{{interface|name}}_ServiceFactory) ServiceDescription() {{descpkg}}ServiceDescription {
return &{{interface|name}}_ServiceDescription{}
}
func (f *{{interface|name}}_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
request := {{interface|name}}_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
f.Delegate.Create(request)
}
// CreateMessagePipeFor{{interface|name}} creates a message pipe for use with the
// {{interface|name}} interface with a {{interface|name}}_Request on one end and a {{interface|name}}_Pointer on the other.
func CreateMessagePipeFor{{interface|name}}() ({{interface|name}}_Request, {{interface|name}}_Pointer) {
r, p := bindings.CreateMessagePipeForMojoInterface()
return {{interface|name}}_Request(r), {{interface|name}}_Pointer(p)
}
{% for method in interface.methods %}
const {{interface|name(False)}}_{{method|name}}_Name uint32 = {{method.ordinal}}
{% endfor %}
type {{interface|name}}_Proxy struct {
router *bindings.Router
ids bindings.Counter
}
func New{{interface|name}}Proxy(p {{interface|name}}_Pointer, waiter bindings.AsyncWaiter) *{{interface|name}}_Proxy {
return &{{interface|name}}_Proxy{
bindings.NewRouter(p.PassMessagePipe(), waiter),
bindings.NewCounter(),
}
}
func (p *{{interface|name}}_Proxy) Close_Proxy() {
p.router.Close()
}
{% for method in interface.methods %}
{{struct_macros.define(method.param_struct, typepkg, pkg, False)}}
{%- if method|has_response %}
{{struct_macros.define(method.response_param_struct, typepkg, pkg, False)}}
{%- endif %}
func (p *{{interface|name}}_Proxy) {{method|name}}{{declare_request_params(method)}} {
payload := &{{method.param_struct|name(False)}}{
{% for field in (method.param_struct).fields %}
{{field|name(False)}},
{% endfor %}
}
header := bindings.MessageHeader{
Type: {{interface|name(False)}}_{{method|name}}_Name,
Flags: {{flags(method, False)}},
{% if method|has_response %}
RequestId: p.ids.Count(),
{% endif %}
}
var message *bindings.Message
if message, err = bindings.EncodeMessage(header, payload); err != nil {
err = fmt.Errorf("can't encode request: %v", err.Error())
p.Close_Proxy()
return
}
{% if method|has_response %}
readResult := <-p.router.AcceptWithResponse(message)
if err = readResult.Error; err != nil {
p.Close_Proxy()
return
}
if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
}
return
}
if got, want := readResult.Message.Header.Type, {{interface|name(False)}}_{{method|name}}_Name; got != want {
err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
}
return
}
var response {{method.response_param_struct|name(False)}}
if err = readResult.Message.DecodePayload(&response); err != nil {
p.Close_Proxy()
return
}
{% for field in (method.response_param_struct).fields %}
{{field|name(False)}} = response.{{field|name(False)}}
{% endfor %}
{% else %}
if err = p.router.Accept(message); err != nil {
p.Close_Proxy()
return
}
{% endif %}
return
}
{% endfor %}
type {{interface|name(False)}}_Stub struct {
connector *bindings.Connector
impl {{interface|name}}
}
func New{{interface|name}}Stub(r {{interface|name}}_Request, impl {{interface|name}}, waiter bindings.AsyncWaiter) *bindings.Stub {
connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
return bindings.NewStub(connector, &{{interface|name(False)}}_Stub{connector, impl})
}
func (f *{{interface|name}}_Request) ServiceDescription() {{descpkg}}ServiceDescription {
return &{{interface|name}}_ServiceDescription{}
}
type {{interface|name}}_ServiceDescription struct{}
{% if should_gen_mojom_types and interface.service_name-%}
func (sd *{{interface|name}}_ServiceDescription) GetTopLevelInterface() (outMojomInterface {{typepkg}}MojomInterface, err error) {
interfaceTypeKey := getRuntimeTypeInfo().Services["{{interface.service_name}}"]
userDefinedType := getRuntimeTypeInfo().TypeMap[interfaceTypeKey].(*{{typepkg}}UserDefinedTypeInterfaceType)
return userDefinedType.Value, nil
}
func (sd *{{interface|name}}_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
return udt, nil
}
return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "{{interface|name}}", inTypeKey)
}
func (sd *{{interface|name}}_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
o := GetAllMojomTypeDefinitions()
return &o, nil
}
{%- else -%}
func (sd *{{interface|name}}_ServiceDescription) GetTopLevelInterface() (outMojomInterface {{typepkg}}MojomInterface, err error) {
err = fmt.Errorf("GetTopLevelInterface not implemented")
return
}
func (sd *{{interface|name}}_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
err = fmt.Errorf("GetTypeDefinition not implemented")
return
}
func (sd *{{interface|name}}_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
err = fmt.Errorf("GetAllTypeDefinitions not implemented")
return
}
{%- endif %}
var _ {{descpkg}}ServiceDescription = (*{{interface|name}}_ServiceDescription)(nil)
func (s *{{interface|name(False)}}_Stub) Accept(message *bindings.Message) (err error) {
switch message.Header.Type {
{% for method in interface.methods %}
case {{interface|name(False)}}_{{method|name}}_Name:
{% if method|has_response %}
if message.Header.Flags != bindings.MessageExpectsResponseFlag {
{% else %}
if message.Header.Flags != bindings.MessageNoFlag {
{% endif %}
return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
}
}
var request {{method.param_struct|name(False)}}
if err := message.DecodePayload(&request); err != nil {
return err
}
{% if method|has_response %}
var response {{method.response_param_struct|name(False)}}
{% endif %}
{% if method.response_parameters|is_none_or_empty %}
err = s.impl.{{method|name}}(
{%- else -%}
{% for field in (method.response_param_struct).fields %}
response.{{field|name(False)}}{{', '}}
{%- endfor -%}err = s.impl.{{method|name}}(
{%- endif -%}
{%- for field in (method.param_struct).fields -%}
request.{{field|name(False)}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
)
if err != nil {
return
}
{% if method|has_response %}
header := bindings.MessageHeader{
Type: {{interface|name(False)}}_{{method|name}}_Name,
Flags: {{flags(method, True)}},
RequestId: message.Header.RequestId,
}
message, err = bindings.EncodeMessage(header, &response)
if err != nil {
return err
}
return s.connector.WriteMessage(message)
{% endif %}
{% endfor %}
default:
return &bindings.ValidationError{
bindings.MessageHeaderUnknownMethod,
fmt.Sprintf("unknown method %v", message.Header.Type),
}
}
return
}
{% endmacro %}