// Copyright 2015 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.
// Source: stress.vdl

package stress

import (
	// VDL system imports
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/vdl"

	// VDL user imports
	"time"
	"v.io/v23/security/access"
	_ "v.io/v23/vdlroot/time"
)

type StressResults struct {
	Iterations  int64
	Qps         float64
	MsecsPerRpc float64
}

func (StressResults) __VDLReflect(struct {
	Name string `vdl:"v.io/x/js.core/stress.StressResults"`
}) {
}

func (m *StressResults) FillVDLTarget(t vdl.Target, tt *vdl.Type) error {

	if __VDLType_stress_v_io_x_js_core_stress_StressResults == nil || __VDLTypestress0 == nil {
		panic("Initialization order error: types generated for FillVDLTarget not initialized. Consider moving caller to an init() block.")
	}
	fieldsTarget1, err := t.StartFields(tt)
	if err != nil {
		return err
	}

	keyTarget2, fieldTarget3, err := fieldsTarget1.StartField("Iterations")
	if err != vdl.ErrFieldNoExist && err != nil {
		return err
	}
	if err != vdl.ErrFieldNoExist {
		if err := fieldTarget3.FromInt(int64(m.Iterations), vdl.Int64Type); err != nil {
			return err
		}
		if err := fieldsTarget1.FinishField(keyTarget2, fieldTarget3); err != nil {
			return err
		}
	}
	keyTarget4, fieldTarget5, err := fieldsTarget1.StartField("Qps")
	if err != vdl.ErrFieldNoExist && err != nil {
		return err
	}
	if err != vdl.ErrFieldNoExist {
		if err := fieldTarget5.FromFloat(float64(m.Qps), vdl.Float64Type); err != nil {
			return err
		}
		if err := fieldsTarget1.FinishField(keyTarget4, fieldTarget5); err != nil {
			return err
		}
	}
	keyTarget6, fieldTarget7, err := fieldsTarget1.StartField("MsecsPerRpc")
	if err != vdl.ErrFieldNoExist && err != nil {
		return err
	}
	if err != vdl.ErrFieldNoExist {
		if err := fieldTarget7.FromFloat(float64(m.MsecsPerRpc), vdl.Float64Type); err != nil {
			return err
		}
		if err := fieldsTarget1.FinishField(keyTarget6, fieldTarget7); err != nil {
			return err
		}
	}
	if err := t.FinishFields(fieldsTarget1); err != nil {
		return err
	}
	return nil
}

func (m *StressResults) MakeVDLTarget() vdl.Target {
	return nil
}

func init() {
	vdl.Register((*StressResults)(nil))
}

var __VDLTypestress0 *vdl.Type = vdl.TypeOf((*StressResults)(nil))
var __VDLType_stress_v_io_x_js_core_stress_StressResults *vdl.Type = vdl.TypeOf(StressResults{})

func __VDLEnsureNativeBuilt_stress() {
}

// StressClientMethods is the client interface
// containing Stress methods.
type StressClientMethods interface {
	// Echo returns the payload that it receives.
	Echo(_ *context.T, Payload []byte, _ ...rpc.CallOpt) ([]byte, error)
	// ServerEcho runs as many calls to Echo on the name provided in the duration
	// specified and returns the peformance results.
	ServerEcho(_ *context.T, totalTime time.Duration, name string, _ ...rpc.CallOpt) (StressResults, error)
}

// StressClientStub adds universal methods to StressClientMethods.
type StressClientStub interface {
	StressClientMethods
	rpc.UniversalServiceMethods
}

// StressClient returns a client stub for Stress.
func StressClient(name string) StressClientStub {
	return implStressClientStub{name}
}

type implStressClientStub struct {
	name string
}

func (c implStressClientStub) Echo(ctx *context.T, i0 []byte, opts ...rpc.CallOpt) (o0 []byte, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "Echo", []interface{}{i0}, []interface{}{&o0}, opts...)
	return
}

func (c implStressClientStub) ServerEcho(ctx *context.T, i0 time.Duration, i1 string, opts ...rpc.CallOpt) (o0 StressResults, err error) {
	err = v23.GetClient(ctx).Call(ctx, c.name, "ServerEcho", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
	return
}

// StressServerMethods is the interface a server writer
// implements for Stress.
type StressServerMethods interface {
	// Echo returns the payload that it receives.
	Echo(_ *context.T, _ rpc.ServerCall, Payload []byte) ([]byte, error)
	// ServerEcho runs as many calls to Echo on the name provided in the duration
	// specified and returns the peformance results.
	ServerEcho(_ *context.T, _ rpc.ServerCall, totalTime time.Duration, name string) (StressResults, error)
}

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

// StressServerStub adds universal methods to StressServerStubMethods.
type StressServerStub interface {
	StressServerStubMethods
	// Describe the Stress interfaces.
	Describe__() []rpc.InterfaceDesc
}

// StressServer returns a server stub for Stress.
// It converts an implementation of StressServerMethods into
// an object that may be used by rpc.Server.
func StressServer(impl StressServerMethods) StressServerStub {
	stub := implStressServerStub{
		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 implStressServerStub struct {
	impl StressServerMethods
	gs   *rpc.GlobState
}

func (s implStressServerStub) Echo(ctx *context.T, call rpc.ServerCall, i0 []byte) ([]byte, error) {
	return s.impl.Echo(ctx, call, i0)
}

func (s implStressServerStub) ServerEcho(ctx *context.T, call rpc.ServerCall, i0 time.Duration, i1 string) (StressResults, error) {
	return s.impl.ServerEcho(ctx, call, i0, i1)
}

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

func (s implStressServerStub) Describe__() []rpc.InterfaceDesc {
	return []rpc.InterfaceDesc{StressDesc}
}

// StressDesc describes the Stress interface.
var StressDesc rpc.InterfaceDesc = descStress

// descStress hides the desc to keep godoc clean.
var descStress = rpc.InterfaceDesc{
	Name:    "Stress",
	PkgPath: "v.io/x/js.core/stress",
	Methods: []rpc.MethodDesc{
		{
			Name: "Echo",
			Doc:  "// Echo returns the payload that it receives.",
			InArgs: []rpc.ArgDesc{
				{"Payload", ``}, // []byte
			},
			OutArgs: []rpc.ArgDesc{
				{"", ``}, // []byte
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Read"))},
		},
		{
			Name: "ServerEcho",
			Doc:  "// ServerEcho runs as many calls to Echo on the name provided in the duration\n// specified and returns the peformance results.",
			InArgs: []rpc.ArgDesc{
				{"totalTime", ``}, // time.Duration
				{"name", ``},      // string
			},
			OutArgs: []rpc.ArgDesc{
				{"", ``}, // StressResults
			},
			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Read"))},
		},
	},
}
