// Code generated by fidlgen; DO NOT EDIT.

package inheritance

import (
	_bindings "syscall/zx/fidl"
)

type superWithCtxFooRequest struct {
	_ struct{} `fidl:"s" fidl_size_v1:"16" fidl_alignment_v1:"8"`
	S string   `fidl_offset_v1:"0" fidl_bounds:""`
}

var _msuperWithCtxFooRequest = _bindings.CreateLazyMarshaler(superWithCtxFooRequest{})

func (msg *superWithCtxFooRequest) Marshaler() _bindings.Marshaler {
	return _msuperWithCtxFooRequest
}

type superWithCtxFooResponse struct {
	_ struct{} `fidl:"s" fidl_size_v1:"8" fidl_alignment_v1:"8"`
	Y int64    `fidl_offset_v1:"0"`
}

var _msuperWithCtxFooResponse = _bindings.CreateLazyMarshaler(superWithCtxFooResponse{})

func (msg *superWithCtxFooResponse) Marshaler() _bindings.Marshaler {
	return _msuperWithCtxFooResponse
}

type subWithCtxFooRequest struct {
	_ struct{} `fidl:"s" fidl_size_v1:"16" fidl_alignment_v1:"8"`
	S string   `fidl_offset_v1:"0" fidl_bounds:""`
}

var _msubWithCtxFooRequest = _bindings.CreateLazyMarshaler(subWithCtxFooRequest{})

func (msg *subWithCtxFooRequest) Marshaler() _bindings.Marshaler {
	return _msubWithCtxFooRequest
}

type subWithCtxFooResponse struct {
	_ struct{} `fidl:"s" fidl_size_v1:"8" fidl_alignment_v1:"8"`
	Y int64    `fidl_offset_v1:"0"`
}

var _msubWithCtxFooResponse = _bindings.CreateLazyMarshaler(subWithCtxFooResponse{})

func (msg *subWithCtxFooResponse) Marshaler() _bindings.Marshaler {
	return _msubWithCtxFooResponse
}

const (
	SuperFooOrdinal uint64 = 0x45602cf3b581d6ab
)

type SuperWithCtxInterface _bindings.ChannelProxy

func (p *SuperWithCtxInterface) Foo(ctx_ _bindings.Context, s string) (int64, error) {
	req_ := &superWithCtxFooRequest{
		S: s,
	}
	resp_ := &superWithCtxFooResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(SuperFooOrdinal, req_, resp_)
	return resp_.Y, err_
}

type SuperWithCtx interface {
	Foo(ctx_ _bindings.Context, s string) (int64, error)
}

type SuperWithCtxTransitionalBase struct{}

type SuperWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewSuperWithCtxInterfaceRequest() (SuperWithCtxInterfaceRequest, *SuperWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return SuperWithCtxInterfaceRequest(req), (*SuperWithCtxInterface)(cli), err
}

type SuperWithCtxStub struct {
	Impl SuperWithCtx
}

func (s_ *SuperWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case SuperFooOrdinal:
		in_ := superWithCtxFooRequest{}
		marshalerCtx, ok := _bindings.GetMarshalerContext(args_.Ctx)
		if !ok {
			return nil, false, _bindings.ErrMissingMarshalerContext
		}
		if _, _, err_ := _bindings.UnmarshalWithContext2(marshalerCtx, args_.Bytes, args_.HandleInfos, &in_); err_ != nil {
			return nil, false, err_
		}
		y, err_ := s_.Impl.Foo(args_.Ctx, in_.S)
		out_ := superWithCtxFooResponse{}
		out_.Y = y
		return &out_, true, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type SuperEventProxy _bindings.ChannelProxy

const (
	SubFooOrdinal uint64 = 0x45602cf3b581d6ab
)

type SubWithCtxInterface _bindings.ChannelProxy

func (p *SubWithCtxInterface) Foo(ctx_ _bindings.Context, s string) (int64, error) {
	req_ := &subWithCtxFooRequest{
		S: s,
	}
	resp_ := &subWithCtxFooResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(SubFooOrdinal, req_, resp_)
	return resp_.Y, err_
}

type SubWithCtx interface {
	Foo(ctx_ _bindings.Context, s string) (int64, error)
}

type SubWithCtxTransitionalBase struct{}

type SubWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewSubWithCtxInterfaceRequest() (SubWithCtxInterfaceRequest, *SubWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return SubWithCtxInterfaceRequest(req), (*SubWithCtxInterface)(cli), err
}

type SubWithCtxStub struct {
	Impl SubWithCtx
}

func (s_ *SubWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case SubFooOrdinal:
		in_ := subWithCtxFooRequest{}
		marshalerCtx, ok := _bindings.GetMarshalerContext(args_.Ctx)
		if !ok {
			return nil, false, _bindings.ErrMissingMarshalerContext
		}
		if _, _, err_ := _bindings.UnmarshalWithContext2(marshalerCtx, args_.Bytes, args_.HandleInfos, &in_); err_ != nil {
			return nil, false, err_
		}
		y, err_ := s_.Impl.Foo(args_.Ctx, in_.S)
		out_ := subWithCtxFooResponse{}
		out_.Y = y
		return &out_, true, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type SubEventProxy _bindings.ChannelProxy
