// 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: errors.vdl

package rpc

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

var (
	// Internal errors.
	errBadRequest                    = verror.Register("v.io/x/ref/runtime/internal/rpc.badRequest", verror.NoRetry, "{1:}{2:} failed to decode request: {3}")
	errBadNumInputArgs               = verror.Register("v.io/x/ref/runtime/internal/rpc.badNumInputArgs", verror.NoRetry, "{1:}{2:} wrong number of input arguments for {3}.{4} (called with {5} args, want {6})")
	errBadInputArg                   = verror.Register("v.io/x/ref/runtime/internal/rpc.badInputArg", verror.NoRetry, "{1:}{2:} failed to decode request {3}.{4} arg #{5}: {6}")
	errBadBlessings                  = verror.Register("v.io/x/ref/runtime/internal/rpc.badBlessings", verror.NoRetry, "{1:}{2:} failed to decode blessings: {3}")
	errBadBlessingsCache             = verror.Register("v.io/x/ref/runtime/internal/rpc.badBlessingsCache", verror.NoRetry, "{1:}{2:} failed to find blessings in cache: {3}")
	errBadDischarge                  = verror.Register("v.io/x/ref/runtime/internal/rpc.badDischarge", verror.NoRetry, "{1:}{2:} failed to decode discharge #{3}: {4}")
	errBadAuth                       = verror.Register("v.io/x/ref/runtime/internal/rpc.badAuth", verror.NoRetry, "{1:}{2:} not authorized to call {3}.{4}: {5}")
	errTypeFlowFailure               = verror.Register("v.io/x/ref/runtime/internal/rpc.typeFlowFailure", verror.NoRetry, "{1:}{2:} type flow could not be constructed{:3}")
	errServerBlessingsWrongPublicKey = verror.Register("v.io/x/ref/runtime/internal/rpc.serverBlessingsWrongPublicKey", verror.NoRetry, "{1:}{2:} server blessings do not match the principals public key")
	errServerPeersEmpty              = verror.Register("v.io/x/ref/runtime/internal/rpc.serverPeersEmpty", verror.NoRetry, "{1:}{2:} no peers are authorized to communicate with the server")
	errServerPeersWithPublishing     = verror.Register("v.io/x/ref/runtime/internal/rpc.serverPeersWithPublishing", verror.NoRetry, "{1:}{2:} ServerPeers option is not supported for servers that publish their endpoint at a mounttable")
)

func init() {
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadRequest.ID), "{1:}{2:} failed to decode request: {3}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadNumInputArgs.ID), "{1:}{2:} wrong number of input arguments for {3}.{4} (called with {5} args, want {6})")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadInputArg.ID), "{1:}{2:} failed to decode request {3}.{4} arg #{5}: {6}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadBlessings.ID), "{1:}{2:} failed to decode blessings: {3}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadBlessingsCache.ID), "{1:}{2:} failed to find blessings in cache: {3}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadDischarge.ID), "{1:}{2:} failed to decode discharge #{3}: {4}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errBadAuth.ID), "{1:}{2:} not authorized to call {3}.{4}: {5}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errTypeFlowFailure.ID), "{1:}{2:} type flow could not be constructed{:3}")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errServerBlessingsWrongPublicKey.ID), "{1:}{2:} server blessings do not match the principals public key")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errServerPeersEmpty.ID), "{1:}{2:} no peers are authorized to communicate with the server")
	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(errServerPeersWithPublishing.ID), "{1:}{2:} ServerPeers option is not supported for servers that publish their endpoint at a mounttable")
}

// newErrBadRequest returns an error with the errBadRequest ID.
func newErrBadRequest(ctx *context.T, err error) error {
	return verror.New(errBadRequest, ctx, err)
}

// newErrBadNumInputArgs returns an error with the errBadNumInputArgs ID.
func newErrBadNumInputArgs(ctx *context.T, suffix string, method string, numCalled uint64, numWanted uint64) error {
	return verror.New(errBadNumInputArgs, ctx, suffix, method, numCalled, numWanted)
}

// newErrBadInputArg returns an error with the errBadInputArg ID.
func newErrBadInputArg(ctx *context.T, suffix string, method string, index uint64, err error) error {
	return verror.New(errBadInputArg, ctx, suffix, method, index, err)
}

// newErrBadBlessings returns an error with the errBadBlessings ID.
func newErrBadBlessings(ctx *context.T, err error) error {
	return verror.New(errBadBlessings, ctx, err)
}

// newErrBadBlessingsCache returns an error with the errBadBlessingsCache ID.
func newErrBadBlessingsCache(ctx *context.T, err error) error {
	return verror.New(errBadBlessingsCache, ctx, err)
}

// newErrBadDischarge returns an error with the errBadDischarge ID.
func newErrBadDischarge(ctx *context.T, index uint64, err error) error {
	return verror.New(errBadDischarge, ctx, index, err)
}

// newErrBadAuth returns an error with the errBadAuth ID.
func newErrBadAuth(ctx *context.T, suffix string, method string, err error) error {
	return verror.New(errBadAuth, ctx, suffix, method, err)
}

// newErrTypeFlowFailure returns an error with the errTypeFlowFailure ID.
func newErrTypeFlowFailure(ctx *context.T, err error) error {
	return verror.New(errTypeFlowFailure, ctx, err)
}

// newErrServerBlessingsWrongPublicKey returns an error with the errServerBlessingsWrongPublicKey ID.
func newErrServerBlessingsWrongPublicKey(ctx *context.T) error {
	return verror.New(errServerBlessingsWrongPublicKey, ctx)
}

// newErrServerPeersEmpty returns an error with the errServerPeersEmpty ID.
func newErrServerPeersEmpty(ctx *context.T) error {
	return verror.New(errServerPeersEmpty, ctx)
}

// newErrServerPeersWithPublishing returns an error with the errServerPeersWithPublishing ID.
func newErrServerPeersWithPublishing(ctx *context.T) error {
	return verror.New(errServerPeersWithPublishing, ctx)
}
