// Code generated by fidlgen; DO NOT EDIT.

package transitivedependenciescompose

import (
	bottom "fidl/bottom"
	_bindings "syscall/zx/fidl"
)

type topWithCtxGetFooResponse struct {
	_   struct{}   `fidl:"s" fidl_size_v1:"8" fidl_alignment_v1:"8"`
	Foo bottom.Foo `fidl_offset_v1:"0"`
}

var _mtopWithCtxGetFooResponse = _bindings.CreateLazyMarshaler(topWithCtxGetFooResponse{})

func (msg *topWithCtxGetFooResponse) Marshaler() _bindings.Marshaler {
	return _mtopWithCtxGetFooResponse
}

const (
	TopGetFooOrdinal uint64 = 0x2c8ccb022c3c571f
)

type TopWithCtxInterface _bindings.ChannelProxy

func (p *TopWithCtxInterface) GetFoo(ctx_ _bindings.Context) (bottom.Foo, error) {
	var req_ _bindings.Message
	resp_ := &topWithCtxGetFooResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(TopGetFooOrdinal, req_, resp_)
	return resp_.Foo, err_
}

type TopWithCtx interface {
	GetFoo(ctx_ _bindings.Context) (bottom.Foo, error)
}

type TopWithCtxTransitionalBase struct{}

type TopWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewTopWithCtxInterfaceRequest() (TopWithCtxInterfaceRequest, *TopWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return TopWithCtxInterfaceRequest(req), (*TopWithCtxInterface)(cli), err
}

type TopWithCtxStub struct {
	Impl TopWithCtx
}

func (s_ *TopWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case TopGetFooOrdinal:
		foo, err_ := s_.Impl.GetFoo(args_.Ctx)
		out_ := topWithCtxGetFooResponse{}
		out_.Foo = foo
		return &out_, true, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type TopEventProxy _bindings.ChannelProxy
