// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file was auto-generated by the vanadium vdl tool.
// Package: allocator

package allocator

import (
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
)

var _ = __VDLInit() // Must be first; see __VDLInit comments for details.

//////////////////////////////////////////////////
// Interface definitions

// AllocatorClientMethods is the client interface
// containing Allocator methods.
type AllocatorClientMethods interface {
	// Create creates a new instance of the service.
	// It returns the object name of the new instance.
	Create(*context.T, ...rpc.CallOpt) (name string, _ error)
	// Destroy destroys the instance with the given name.
	Destroy(_ *context.T, name string, _ ...rpc.CallOpt) error
	// List returns a list of all the instances owned by the caller.
	List(*context.T, ...rpc.CallOpt) (names []string, _ error)
}

// AllocatorClientStub adds universal methods to AllocatorClientMethods.
type AllocatorClientStub interface {
	AllocatorClientMethods
	rpc.UniversalServiceMethods
}

// AllocatorClient returns a client stub for Allocator.
func AllocatorClient(name string) AllocatorClientStub {
	return implAllocatorClientStub{name}
}

type implAllocatorClientStub struct {
	name string
}

func (c implAllocatorClientStub) Create(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "Create", nil, []interface{}{&o0}, opts...)
	return
}

func (c implAllocatorClientStub) Destroy(ctx *context.T, i0 string, opts ...rpc.CallOpt) (err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "Destroy", []interface{}{i0}, nil, opts...)
	return
}

func (c implAllocatorClientStub) List(ctx *context.T, opts ...rpc.CallOpt) (o0 []string, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "List", nil, []interface{}{&o0}, opts...)
	return
}

// AllocatorServerMethods is the interface a server writer
// implements for Allocator.
type AllocatorServerMethods interface {
	// Create creates a new instance of the service.
	// It returns the object name of the new instance.
	Create(*context.T, rpc.ServerCall) (name string, _ error)
	// Destroy destroys the instance with the given name.
	Destroy(_ *context.T, _ rpc.ServerCall, name string) error
	// List returns a list of all the instances owned by the caller.
	List(*context.T, rpc.ServerCall) (names []string, _ error)
}

// AllocatorServerStubMethods is the server interface containing
// Allocator methods, as expected by rpc.Server.
// There is no difference between this interface and AllocatorServerMethods
// since there are no streaming methods.
type AllocatorServerStubMethods AllocatorServerMethods

// AllocatorServerStub adds universal methods to AllocatorServerStubMethods.
type AllocatorServerStub interface {
	AllocatorServerStubMethods
	// Describe the Allocator interfaces.
	Describe__() []rpc.InterfaceDesc
}

// AllocatorServer returns a server stub for Allocator.
// It converts an implementation of AllocatorServerMethods into
// an object that may be used by rpc.Server.
func AllocatorServer(impl AllocatorServerMethods) AllocatorServerStub {
	stub := implAllocatorServerStub{
		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 := rpc.NewGlobState(stub); gs != nil {
		stub.gs = gs
	} else if gs := rpc.NewGlobState(impl); gs != nil {
		stub.gs = gs
	}
	return stub
}

type implAllocatorServerStub struct {
	impl AllocatorServerMethods
	gs   *rpc.GlobState
}

func (s implAllocatorServerStub) Create(ctx *context.T, call rpc.ServerCall) (string, error) {
	return s.impl.Create(ctx, call)
}

func (s implAllocatorServerStub) Destroy(ctx *context.T, call rpc.ServerCall, i0 string) error {
	return s.impl.Destroy(ctx, call, i0)
}

func (s implAllocatorServerStub) List(ctx *context.T, call rpc.ServerCall) ([]string, error) {
	return s.impl.List(ctx, call)
}

func (s implAllocatorServerStub) Globber() *rpc.GlobState {
	return s.gs
}

func (s implAllocatorServerStub) Describe__() []rpc.InterfaceDesc {
	return []rpc.InterfaceDesc{AllocatorDesc}
}

// AllocatorDesc describes the Allocator interface.
var AllocatorDesc rpc.InterfaceDesc = descAllocator

// descAllocator hides the desc to keep godoc clean.
var descAllocator = rpc.InterfaceDesc{
	Name:    "Allocator",
	PkgPath: "v.io/x/ref/services/allocator",
	Methods: []rpc.MethodDesc{
		{
			Name: "Create",
			Doc:  "// Create creates a new instance of the service.\n// It returns the object name of the new instance.",
			OutArgs: []rpc.ArgDesc{
				{"name", ``}, // string
			},
		},
		{
			Name: "Destroy",
			Doc:  "// Destroy destroys the instance with the given name.",
			InArgs: []rpc.ArgDesc{
				{"name", ``}, // string
			},
		},
		{
			Name: "List",
			Doc:  "// List returns a list of all the instances owned by the caller.",
			OutArgs: []rpc.ArgDesc{
				{"names", ``}, // []string
			},
		},
	},
}

var __VDLInitCalled bool

// __VDLInit performs vdl initialization.  It is safe to call multiple times.
// If you have an init ordering issue, just insert the following line verbatim
// into your source files in this package, right after the "package foo" clause:
//
//    var _ = __VDLInit()
//
// The purpose of this function is to ensure that vdl initialization occurs in
// the right order, and very early in the init sequence.  In particular, vdl
// registration and package variable initialization needs to occur before
// functions like vdl.TypeOf will work properly.
//
// This function returns a dummy value, so that it can be used to initialize the
// first var in the file, to take advantage of Go's defined init order.
func __VDLInit() struct{} {
	if __VDLInitCalled {
		return struct{}{}
	}
	__VDLInitCalled = true

	return struct{}{}
}
