// Code generated by fidlgen; DO NOT EDIT.

package requestflexibleenvelope

import (
	_bindings "syscall/zx/fidl"
)

type protocolWithCtxRequestStrictResponseFlexibleRequest struct {
	_ struct{}  `fidl:"s" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	S StrictFoo `fidl_offset_v1:"0"`
}

var _mprotocolWithCtxRequestStrictResponseFlexibleRequest = _bindings.CreateLazyMarshaler(protocolWithCtxRequestStrictResponseFlexibleRequest{})

func (msg *protocolWithCtxRequestStrictResponseFlexibleRequest) Marshaler() _bindings.Marshaler {
	return _mprotocolWithCtxRequestStrictResponseFlexibleRequest
}

type protocolWithCtxRequestStrictResponseFlexibleResponse struct {
	_ struct{}    `fidl:"s" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	F FlexibleFoo `fidl_offset_v1:"0"`
}

var _mprotocolWithCtxRequestStrictResponseFlexibleResponse = _bindings.CreateLazyMarshaler(protocolWithCtxRequestStrictResponseFlexibleResponse{})

func (msg *protocolWithCtxRequestStrictResponseFlexibleResponse) Marshaler() _bindings.Marshaler {
	return _mprotocolWithCtxRequestStrictResponseFlexibleResponse
}

type protocolWithCtxRequestFlexibleResponseStrictRequest struct {
	_ struct{}    `fidl:"s" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	S FlexibleFoo `fidl_offset_v1:"0"`
}

var _mprotocolWithCtxRequestFlexibleResponseStrictRequest = _bindings.CreateLazyMarshaler(protocolWithCtxRequestFlexibleResponseStrictRequest{})

func (msg *protocolWithCtxRequestFlexibleResponseStrictRequest) Marshaler() _bindings.Marshaler {
	return _mprotocolWithCtxRequestFlexibleResponseStrictRequest
}

type protocolWithCtxRequestFlexibleResponseStrictResponse struct {
	_ struct{}  `fidl:"s" fidl_size_v1:"24" fidl_alignment_v1:"8"`
	F StrictFoo `fidl_offset_v1:"0"`
}

var _mprotocolWithCtxRequestFlexibleResponseStrictResponse = _bindings.CreateLazyMarshaler(protocolWithCtxRequestFlexibleResponseStrictResponse{})

func (msg *protocolWithCtxRequestFlexibleResponseStrictResponse) Marshaler() _bindings.Marshaler {
	return _mprotocolWithCtxRequestFlexibleResponseStrictResponse
}

type I_flexibleFooTag uint64

const (
	FlexibleFoo_unknownData = 0 // 0x00000000
	FlexibleFooS            = 1 // 0x00000001
	FlexibleFooI            = 2 // 0x00000002
)

type FlexibleFoo struct {
	I_flexibleFooTag `fidl:"x" fidl_size_v1:"24" fidl_alignment_v1:"8" fidl_resource:"false"`
	I_unknownData    interface{}
	S                string `fidl_bounds:"" fidl_ordinal:"1"`
	I                int32  `fidl_ordinal:"2"`
}

func (_m *FlexibleFoo) reset() {
	switch _m.I_flexibleFooTag {
	case 1:
		var _zeroed string
		_m.S = _zeroed
	case 2:
		var _zeroed int32
		_m.I = _zeroed
	default:
		var _zeroed interface{}
		_m.I_unknownData = _zeroed
	}
}

func (_m *FlexibleFoo) Which() I_flexibleFooTag {
	switch _m.I_flexibleFooTag {
	case 1:
		return FlexibleFooS
	case 2:
		return FlexibleFooI
	default:
		return FlexibleFoo_unknownData
	}
}

func (_m *FlexibleFoo) Ordinal() uint64 {
	return uint64(_m.I_flexibleFooTag)
}

func (_m *FlexibleFoo) SetS(s string) {
	_m.reset()
	_m.I_flexibleFooTag = FlexibleFooS
	_m.S = s
}

func FlexibleFooWithS(s string) FlexibleFoo {
	var _u FlexibleFoo
	_u.SetS(s)
	return _u
}

func (_m *FlexibleFoo) SetI(i int32) {
	_m.reset()
	_m.I_flexibleFooTag = FlexibleFooI
	_m.I = i
}

func FlexibleFooWithI(i int32) FlexibleFoo {
	var _u FlexibleFoo
	_u.SetI(i)
	return _u
}
func (_m *FlexibleFoo) GetUnknownData() _bindings.UnknownData {
	return _m.I_unknownData.(_bindings.UnknownData)
}

type I_strictFooTag uint64

const (
	StrictFooS = 1 // 0x00000001
	StrictFooI = 2 // 0x00000002
)

type StrictFoo struct {
	I_strictFooTag `fidl:"x!" fidl_size_v1:"24" fidl_alignment_v1:"8" fidl_resource:"false"`
	S              string `fidl_bounds:"" fidl_ordinal:"1"`
	I              int32  `fidl_ordinal:"2"`
}

func (_m *StrictFoo) reset() {
	switch _m.I_strictFooTag {
	case 1:
		var _zeroed string
		_m.S = _zeroed
	case 2:
		var _zeroed int32
		_m.I = _zeroed
	}
}

func (_m *StrictFoo) Which() I_strictFooTag {
	return _m.I_strictFooTag
}

func (_m *StrictFoo) Ordinal() uint64 {
	return uint64(_m.I_strictFooTag)
}

func (_m *StrictFoo) SetS(s string) {
	_m.reset()
	_m.I_strictFooTag = StrictFooS
	_m.S = s
}

func StrictFooWithS(s string) StrictFoo {
	var _u StrictFoo
	_u.SetS(s)
	return _u
}

func (_m *StrictFoo) SetI(i int32) {
	_m.reset()
	_m.I_strictFooTag = StrictFooI
	_m.I = i
}

func StrictFooWithI(i int32) StrictFoo {
	var _u StrictFoo
	_u.SetI(i)
	return _u
}

const (
	ProtocolRequestStrictResponseFlexibleOrdinal uint64 = 0x3c5330c58686011a
	ProtocolRequestFlexibleResponseStrictOrdinal uint64 = 0x3cb49d8f6e204f76
)

type ProtocolWithCtxInterface _bindings.ChannelProxy

func (p *ProtocolWithCtxInterface) RequestStrictResponseFlexible(ctx_ _bindings.Context, s StrictFoo) (FlexibleFoo, error) {
	req_ := &protocolWithCtxRequestStrictResponseFlexibleRequest{
		S: s,
	}
	resp_ := &protocolWithCtxRequestStrictResponseFlexibleResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(ProtocolRequestStrictResponseFlexibleOrdinal, req_, resp_)
	return resp_.F, err_
}

func (p *ProtocolWithCtxInterface) RequestFlexibleResponseStrict(ctx_ _bindings.Context, s FlexibleFoo) (StrictFoo, error) {
	req_ := &protocolWithCtxRequestFlexibleResponseStrictRequest{
		S: s,
	}
	resp_ := &protocolWithCtxRequestFlexibleResponseStrictResponse{}
	err_ := ((*_bindings.ChannelProxy)(p)).Call(ProtocolRequestFlexibleResponseStrictOrdinal, req_, resp_)
	return resp_.F, err_
}

type ProtocolWithCtx interface {
	RequestStrictResponseFlexible(ctx_ _bindings.Context, s StrictFoo) (FlexibleFoo, error)
	RequestFlexibleResponseStrict(ctx_ _bindings.Context, s FlexibleFoo) (StrictFoo, error)
}

type ProtocolWithCtxTransitionalBase struct{}

type ProtocolWithCtxInterfaceRequest _bindings.InterfaceRequest

func NewProtocolWithCtxInterfaceRequest() (ProtocolWithCtxInterfaceRequest, *ProtocolWithCtxInterface, error) {
	req, cli, err := _bindings.NewInterfaceRequest()
	return ProtocolWithCtxInterfaceRequest(req), (*ProtocolWithCtxInterface)(cli), err
}

type ProtocolWithCtxStub struct {
	Impl ProtocolWithCtx
}

func (s_ *ProtocolWithCtxStub) Dispatch(args_ _bindings.DispatchArgs) (_bindings.Message, bool, error) {
	switch args_.Ordinal {
	case ProtocolRequestStrictResponseFlexibleOrdinal:
		in_ := protocolWithCtxRequestStrictResponseFlexibleRequest{}
		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_
		}
		f, err_ := s_.Impl.RequestStrictResponseFlexible(args_.Ctx, in_.S)
		out_ := protocolWithCtxRequestStrictResponseFlexibleResponse{}
		out_.F = f
		return &out_, true, err_
	case ProtocolRequestFlexibleResponseStrictOrdinal:
		in_ := protocolWithCtxRequestFlexibleResponseStrictRequest{}
		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_
		}
		f, err_ := s_.Impl.RequestFlexibleResponseStrict(args_.Ctx, in_.S)
		out_ := protocolWithCtxRequestFlexibleResponseStrictResponse{}
		out_.F = f
		return &out_, true, err_
	}
	return nil, false, _bindings.ErrUnknownOrdinal
}

type ProtocolEventProxy _bindings.ChannelProxy
