// 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.
// Package: internal

package internal

import (
	"v.io/v23/security"
	"v.io/v23/uniqueid"
	"v.io/v23/vdl"
)

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

//////////////////////////////////////////////////
// Type definitions

// Config contains the attributes of the role, and the list of members who have
// access to it.
type Config struct {
	// List of role objects, relative to this role, from which to import
	// the set of members. File path notation like "." and ".." may be used.
	// The set of members who have access to this role is the union of this
	// role's members and those of all the imported roles.
	ImportMembers []string
	// Blessings that match at least one of the patterns in this set are
	// allowed to act on behalf of the role.
	Members []security.BlessingPattern
	// Indicates that the blessing name of the caller should be appended to
	// the role blessing name.
	Extend bool
	// If Audit is true, each use of the role blessing will be reported to
	// an auditing service and will be usable only if the report was
	// successful.
	Audit bool
	// The amount of time for which the role blessing will be valid. It is a
	// string representation of a time.Duration, e.g. "24h". An empty string
	// indicates that the role blessing will not expire.
	Expiry string
	// The blessings issued for this role will only be valid for
	// communicating with peers that match at least one of these patterns.
	// If the list is empty, all peers are allowed.
	Peers []security.BlessingPattern
}

func (Config) __VDLReflect(struct {
	Name string `vdl:"v.io/x/ref/services/role/roled/internal.Config"`
}) {
}

func (x Config) VDLIsZero() bool {
	if len(x.ImportMembers) != 0 {
		return false
	}
	if len(x.Members) != 0 {
		return false
	}
	if x.Extend {
		return false
	}
	if x.Audit {
		return false
	}
	if x.Expiry != "" {
		return false
	}
	if len(x.Peers) != 0 {
		return false
	}
	return true
}

func (x Config) VDLWrite(enc vdl.Encoder) error {
	if err := enc.StartValue(__VDLType_struct_1); err != nil {
		return err
	}
	if len(x.ImportMembers) != 0 {
		if err := enc.NextField("ImportMembers"); err != nil {
			return err
		}
		if err := __VDLWriteAnon_list_1(enc, x.ImportMembers); err != nil {
			return err
		}
	}
	if len(x.Members) != 0 {
		if err := enc.NextField("Members"); err != nil {
			return err
		}
		if err := __VDLWriteAnon_list_2(enc, x.Members); err != nil {
			return err
		}
	}
	if x.Extend {
		if err := enc.NextFieldValueBool("Extend", vdl.BoolType, x.Extend); err != nil {
			return err
		}
	}
	if x.Audit {
		if err := enc.NextFieldValueBool("Audit", vdl.BoolType, x.Audit); err != nil {
			return err
		}
	}
	if x.Expiry != "" {
		if err := enc.NextFieldValueString("Expiry", vdl.StringType, x.Expiry); err != nil {
			return err
		}
	}
	if len(x.Peers) != 0 {
		if err := enc.NextField("Peers"); err != nil {
			return err
		}
		if err := __VDLWriteAnon_list_2(enc, x.Peers); err != nil {
			return err
		}
	}
	if err := enc.NextField(""); err != nil {
		return err
	}
	return enc.FinishValue()
}

func __VDLWriteAnon_list_1(enc vdl.Encoder, x []string) error {
	if err := enc.StartValue(__VDLType_list_2); err != nil {
		return err
	}
	if err := enc.SetLenHint(len(x)); err != nil {
		return err
	}
	for _, elem := range x {
		if err := enc.NextEntryValueString(vdl.StringType, elem); err != nil {
			return err
		}
	}
	if err := enc.NextEntry(true); err != nil {
		return err
	}
	return enc.FinishValue()
}

func __VDLWriteAnon_list_2(enc vdl.Encoder, x []security.BlessingPattern) error {
	if err := enc.StartValue(__VDLType_list_3); err != nil {
		return err
	}
	if err := enc.SetLenHint(len(x)); err != nil {
		return err
	}
	for _, elem := range x {
		if err := enc.NextEntryValueString(__VDLType_string_4, string(elem)); err != nil {
			return err
		}
	}
	if err := enc.NextEntry(true); err != nil {
		return err
	}
	return enc.FinishValue()
}

func (x *Config) VDLRead(dec vdl.Decoder) error {
	*x = Config{}
	if err := dec.StartValue(__VDLType_struct_1); err != nil {
		return err
	}
	for {
		f, err := dec.NextField()
		if err != nil {
			return err
		}
		switch f {
		case "":
			return dec.FinishValue()
		case "ImportMembers":
			if err := __VDLReadAnon_list_1(dec, &x.ImportMembers); err != nil {
				return err
			}
		case "Members":
			if err := __VDLReadAnon_list_2(dec, &x.Members); err != nil {
				return err
			}
		case "Extend":
			switch value, err := dec.ReadValueBool(); {
			case err != nil:
				return err
			default:
				x.Extend = value
			}
		case "Audit":
			switch value, err := dec.ReadValueBool(); {
			case err != nil:
				return err
			default:
				x.Audit = value
			}
		case "Expiry":
			switch value, err := dec.ReadValueString(); {
			case err != nil:
				return err
			default:
				x.Expiry = value
			}
		case "Peers":
			if err := __VDLReadAnon_list_2(dec, &x.Peers); err != nil {
				return err
			}
		default:
			if err := dec.SkipValue(); err != nil {
				return err
			}
		}
	}
}

func __VDLReadAnon_list_1(dec vdl.Decoder, x *[]string) error {
	if err := dec.StartValue(__VDLType_list_2); err != nil {
		return err
	}
	if len := dec.LenHint(); len > 0 {
		*x = make([]string, 0, len)
	} else {
		*x = nil
	}
	for {
		switch done, elem, err := dec.NextEntryValueString(); {
		case err != nil:
			return err
		case done:
			return dec.FinishValue()
		default:
			*x = append(*x, elem)
		}
	}
}

func __VDLReadAnon_list_2(dec vdl.Decoder, x *[]security.BlessingPattern) error {
	if err := dec.StartValue(__VDLType_list_3); err != nil {
		return err
	}
	if len := dec.LenHint(); len > 0 {
		*x = make([]security.BlessingPattern, 0, len)
	} else {
		*x = nil
	}
	for {
		switch done, elem, err := dec.NextEntryValueString(); {
		case err != nil:
			return err
		case done:
			return dec.FinishValue()
		default:
			*x = append(*x, security.BlessingPattern(elem))
		}
	}
}

//////////////////////////////////////////////////
// Const definitions

// LoggingCaveat is a caveat that will always validate but it logs the parameter on every attempt to validate it.
var LoggingCaveat = security.CaveatDescriptor{
	Id: uniqueid.Id{
		176,
		52,
		28,
		237,
		226,
		223,
		129,
		189,
		237,
		112,
		151,
		187,
		85,
		173,
		128,
		0,
	},
	ParamType: __VDLType_list_2,
}

// Hold type definitions in package-level variables, for better performance.
var (
	__VDLType_struct_1 *vdl.Type
	__VDLType_list_2   *vdl.Type
	__VDLType_list_3   *vdl.Type
	__VDLType_string_4 *vdl.Type
)

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

	// Register types.
	vdl.Register((*Config)(nil))

	// Initialize type definitions.
	__VDLType_struct_1 = vdl.TypeOf((*Config)(nil)).Elem()
	__VDLType_list_2 = vdl.TypeOf((*[]string)(nil))
	__VDLType_list_3 = vdl.TypeOf((*[]security.BlessingPattern)(nil))
	__VDLType_string_4 = vdl.TypeOf((*security.BlessingPattern)(nil))

	return struct{}{}
}
