// This file was auto-generated by the veyron vdl tool.
// Source: exp.vdl

// Package exp is used to test that embedding interfaces works across packages.
// The arith.Calculator vdl interface embeds the Exp interface.
package exp

import (
	// VDL system imports
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/ipc"
)

// ExpClientMethods is the client interface
// containing Exp methods.
type ExpClientMethods interface {
	Exp(ctx *context.T, x float64, opts ...ipc.CallOpt) (float64, error)
}

// ExpClientStub adds universal methods to ExpClientMethods.
type ExpClientStub interface {
	ExpClientMethods
	ipc.UniversalServiceMethods
}

// ExpClient returns a client stub for Exp.
func ExpClient(name string, opts ...ipc.BindOpt) ExpClientStub {
	var client ipc.Client
	for _, opt := range opts {
		if clientOpt, ok := opt.(ipc.Client); ok {
			client = clientOpt
		}
	}
	return implExpClientStub{name, client}
}

type implExpClientStub struct {
	name   string
	client ipc.Client
}

func (c implExpClientStub) c(ctx *context.T) ipc.Client {
	if c.client != nil {
		return c.client
	}
	return v23.GetClient(ctx)
}

func (c implExpClientStub) Exp(ctx *context.T, i0 float64, opts ...ipc.CallOpt) (o0 float64, err error) {
	var call ipc.ClientCall
	if call, err = c.c(ctx).StartCall(ctx, c.name, "Exp", []interface{}{i0}, opts...); err != nil {
		return
	}
	err = call.Finish(&o0)
	return
}

// ExpServerMethods is the interface a server writer
// implements for Exp.
type ExpServerMethods interface {
	Exp(call ipc.ServerCall, x float64) (float64, error)
}

// ExpServerStubMethods is the server interface containing
// Exp methods, as expected by ipc.Server.
// There is no difference between this interface and ExpServerMethods
// since there are no streaming methods.
type ExpServerStubMethods ExpServerMethods

// ExpServerStub adds universal methods to ExpServerStubMethods.
type ExpServerStub interface {
	ExpServerStubMethods
	// Describe the Exp interfaces.
	Describe__() []ipc.InterfaceDesc
}

// ExpServer returns a server stub for Exp.
// It converts an implementation of ExpServerMethods into
// an object that may be used by ipc.Server.
func ExpServer(impl ExpServerMethods) ExpServerStub {
	stub := implExpServerStub{
		impl: impl,
	}
	// Initialize GlobState; always check the stub itself first, to handle the
	// case where the user has the Glob method defined in their VDL source.
	if gs := ipc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := ipc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implExpServerStub struct {
	impl ExpServerMethods
	gs   *ipc.GlobState
}

func (s implExpServerStub) Exp(call ipc.ServerCall, i0 float64) (float64, error) {
	return s.impl.Exp(call, i0)
}

func (s implExpServerStub) Globber() *ipc.GlobState {
	return s.gs
}

func (s implExpServerStub) Describe__() []ipc.InterfaceDesc {
	return []ipc.InterfaceDesc{ExpDesc}
}

// ExpDesc describes the Exp interface.
var ExpDesc ipc.InterfaceDesc = descExp

// descExp hides the desc to keep godoc clean.
var descExp = ipc.InterfaceDesc{
	Name:    "Exp",
	PkgPath: "v.io/x/ref/lib/vdl/testdata/arith/exp",
	Methods: []ipc.MethodDesc{
		{
			Name: "Exp",
			InArgs: []ipc.ArgDesc{
				{"x", ``}, // float64
			},
			OutArgs: []ipc.ArgDesc{
				{"", ``}, // float64
			},
		},
	},
}
