// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code generated by protoc-gen-go_gapic. DO NOT EDIT.

package iap

import (
	"context"
	"fmt"
	"math"
	"net/url"
	"time"

	gax "github.com/googleapis/gax-go/v2"
	"google.golang.org/api/iterator"
	"google.golang.org/api/option"
	"google.golang.org/api/option/internaloption"
	gtransport "google.golang.org/api/transport/grpc"
	iappb "google.golang.org/genproto/googleapis/cloud/iap/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/proto"
)

var newIdentityAwareProxyOAuthClientHook clientHook

// IdentityAwareProxyOAuthCallOptions contains the retry settings for each method of IdentityAwareProxyOAuthClient.
type IdentityAwareProxyOAuthCallOptions struct {
	ListBrands                          []gax.CallOption
	CreateBrand                         []gax.CallOption
	GetBrand                            []gax.CallOption
	CreateIdentityAwareProxyClient      []gax.CallOption
	ListIdentityAwareProxyClients       []gax.CallOption
	GetIdentityAwareProxyClient         []gax.CallOption
	ResetIdentityAwareProxyClientSecret []gax.CallOption
	DeleteIdentityAwareProxyClient      []gax.CallOption
}

func defaultIdentityAwareProxyOAuthGRPCClientOptions() []option.ClientOption {
	return []option.ClientOption{
		internaloption.WithDefaultEndpoint("iap.googleapis.com:443"),
		internaloption.WithDefaultMTLSEndpoint("iap.mtls.googleapis.com:443"),
		internaloption.WithDefaultAudience("https://iap.googleapis.com/"),
		internaloption.WithDefaultScopes(DefaultAuthScopes()...),
		internaloption.EnableJwtWithScope(),
		option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
			grpc.MaxCallRecvMsgSize(math.MaxInt32))),
	}
}

func defaultIdentityAwareProxyOAuthCallOptions() *IdentityAwareProxyOAuthCallOptions {
	return &IdentityAwareProxyOAuthCallOptions{
		ListBrands:                          []gax.CallOption{},
		CreateBrand:                         []gax.CallOption{},
		GetBrand:                            []gax.CallOption{},
		CreateIdentityAwareProxyClient:      []gax.CallOption{},
		ListIdentityAwareProxyClients:       []gax.CallOption{},
		GetIdentityAwareProxyClient:         []gax.CallOption{},
		ResetIdentityAwareProxyClientSecret: []gax.CallOption{},
		DeleteIdentityAwareProxyClient:      []gax.CallOption{},
	}
}

// internalIdentityAwareProxyOAuthClient is an interface that defines the methods availaible from Cloud Identity-Aware Proxy API.
type internalIdentityAwareProxyOAuthClient interface {
	Close() error
	setGoogleClientInfo(...string)
	Connection() *grpc.ClientConn
	ListBrands(context.Context, *iappb.ListBrandsRequest, ...gax.CallOption) (*iappb.ListBrandsResponse, error)
	CreateBrand(context.Context, *iappb.CreateBrandRequest, ...gax.CallOption) (*iappb.Brand, error)
	GetBrand(context.Context, *iappb.GetBrandRequest, ...gax.CallOption) (*iappb.Brand, error)
	CreateIdentityAwareProxyClient(context.Context, *iappb.CreateIdentityAwareProxyClientRequest, ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error)
	ListIdentityAwareProxyClients(context.Context, *iappb.ListIdentityAwareProxyClientsRequest, ...gax.CallOption) *IdentityAwareProxyClientIterator
	GetIdentityAwareProxyClient(context.Context, *iappb.GetIdentityAwareProxyClientRequest, ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error)
	ResetIdentityAwareProxyClientSecret(context.Context, *iappb.ResetIdentityAwareProxyClientSecretRequest, ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error)
	DeleteIdentityAwareProxyClient(context.Context, *iappb.DeleteIdentityAwareProxyClientRequest, ...gax.CallOption) error
}

// IdentityAwareProxyOAuthClient is a client for interacting with Cloud Identity-Aware Proxy API.
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
//
// API to programmatically create, list and retrieve Identity Aware Proxy (IAP)
// OAuth brands; and create, retrieve, delete and reset-secret of IAP OAuth
// clients.
type IdentityAwareProxyOAuthClient struct {
	// The internal transport-dependent client.
	internalClient internalIdentityAwareProxyOAuthClient

	// The call options for this service.
	CallOptions *IdentityAwareProxyOAuthCallOptions
}

// Wrapper methods routed to the internal client.

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *IdentityAwareProxyOAuthClient) Close() error {
	return c.internalClient.Close()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *IdentityAwareProxyOAuthClient) setGoogleClientInfo(keyval ...string) {
	c.internalClient.setGoogleClientInfo(keyval...)
}

// Connection returns a connection to the API service.
//
// Deprecated.
func (c *IdentityAwareProxyOAuthClient) Connection() *grpc.ClientConn {
	return c.internalClient.Connection()
}

// ListBrands lists the existing brands for the project.
func (c *IdentityAwareProxyOAuthClient) ListBrands(ctx context.Context, req *iappb.ListBrandsRequest, opts ...gax.CallOption) (*iappb.ListBrandsResponse, error) {
	return c.internalClient.ListBrands(ctx, req, opts...)
}

// CreateBrand constructs a new OAuth brand for the project if one does not exist.
// The created brand is “internal only”, meaning that OAuth clients created
// under it only accept requests from users who belong to the same G Suite
// organization as the project. The brand is created in an un-reviewed status.
// NOTE: The “internal only” status can be manually changed in the Google
// Cloud console. Requires that a brand does not already exist for the
// project, and that the specified support email is owned by the caller.
func (c *IdentityAwareProxyOAuthClient) CreateBrand(ctx context.Context, req *iappb.CreateBrandRequest, opts ...gax.CallOption) (*iappb.Brand, error) {
	return c.internalClient.CreateBrand(ctx, req, opts...)
}

// GetBrand retrieves the OAuth brand of the project.
func (c *IdentityAwareProxyOAuthClient) GetBrand(ctx context.Context, req *iappb.GetBrandRequest, opts ...gax.CallOption) (*iappb.Brand, error) {
	return c.internalClient.GetBrand(ctx, req, opts...)
}

// CreateIdentityAwareProxyClient creates an Identity Aware Proxy (IAP) OAuth client. The client is owned
// by IAP. Requires that the brand for the project exists and that it is
// set for internal-only use.
func (c *IdentityAwareProxyOAuthClient) CreateIdentityAwareProxyClient(ctx context.Context, req *iappb.CreateIdentityAwareProxyClientRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	return c.internalClient.CreateIdentityAwareProxyClient(ctx, req, opts...)
}

// ListIdentityAwareProxyClients lists the existing clients for the brand.
func (c *IdentityAwareProxyOAuthClient) ListIdentityAwareProxyClients(ctx context.Context, req *iappb.ListIdentityAwareProxyClientsRequest, opts ...gax.CallOption) *IdentityAwareProxyClientIterator {
	return c.internalClient.ListIdentityAwareProxyClients(ctx, req, opts...)
}

// GetIdentityAwareProxyClient retrieves an Identity Aware Proxy (IAP) OAuth client.
// Requires that the client is owned by IAP.
func (c *IdentityAwareProxyOAuthClient) GetIdentityAwareProxyClient(ctx context.Context, req *iappb.GetIdentityAwareProxyClientRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	return c.internalClient.GetIdentityAwareProxyClient(ctx, req, opts...)
}

// ResetIdentityAwareProxyClientSecret resets an Identity Aware Proxy (IAP) OAuth client secret. Useful if the
// secret was compromised. Requires that the client is owned by IAP.
func (c *IdentityAwareProxyOAuthClient) ResetIdentityAwareProxyClientSecret(ctx context.Context, req *iappb.ResetIdentityAwareProxyClientSecretRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	return c.internalClient.ResetIdentityAwareProxyClientSecret(ctx, req, opts...)
}

// DeleteIdentityAwareProxyClient deletes an Identity Aware Proxy (IAP) OAuth client. Useful for removing
// obsolete clients, managing the number of clients in a given project, and
// cleaning up after tests. Requires that the client is owned by IAP.
func (c *IdentityAwareProxyOAuthClient) DeleteIdentityAwareProxyClient(ctx context.Context, req *iappb.DeleteIdentityAwareProxyClientRequest, opts ...gax.CallOption) error {
	return c.internalClient.DeleteIdentityAwareProxyClient(ctx, req, opts...)
}

// identityAwareProxyOAuthGRPCClient is a client for interacting with Cloud Identity-Aware Proxy API over gRPC transport.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type identityAwareProxyOAuthGRPCClient struct {
	// Connection pool of gRPC connections to the service.
	connPool gtransport.ConnPool

	// flag to opt out of default deadlines via GOOGLE_API_GO_EXPERIMENTAL_DISABLE_DEFAULT_DEADLINE
	disableDeadlines bool

	// Points back to the CallOptions field of the containing IdentityAwareProxyOAuthClient
	CallOptions **IdentityAwareProxyOAuthCallOptions

	// The gRPC API client.
	identityAwareProxyOAuthClient iappb.IdentityAwareProxyOAuthServiceClient

	// The x-goog-* metadata to be sent with each request.
	xGoogMetadata metadata.MD
}

// NewIdentityAwareProxyOAuthClient creates a new identity aware proxyo auth service client based on gRPC.
// The returned client must be Closed when it is done being used to clean up its underlying connections.
//
// API to programmatically create, list and retrieve Identity Aware Proxy (IAP)
// OAuth brands; and create, retrieve, delete and reset-secret of IAP OAuth
// clients.
func NewIdentityAwareProxyOAuthClient(ctx context.Context, opts ...option.ClientOption) (*IdentityAwareProxyOAuthClient, error) {
	clientOpts := defaultIdentityAwareProxyOAuthGRPCClientOptions()
	if newIdentityAwareProxyOAuthClientHook != nil {
		hookOpts, err := newIdentityAwareProxyOAuthClientHook(ctx, clientHookParams{})
		if err != nil {
			return nil, err
		}
		clientOpts = append(clientOpts, hookOpts...)
	}

	disableDeadlines, err := checkDisableDeadlines()
	if err != nil {
		return nil, err
	}

	connPool, err := gtransport.DialPool(ctx, append(clientOpts, opts...)...)
	if err != nil {
		return nil, err
	}
	client := IdentityAwareProxyOAuthClient{CallOptions: defaultIdentityAwareProxyOAuthCallOptions()}

	c := &identityAwareProxyOAuthGRPCClient{
		connPool:                      connPool,
		disableDeadlines:              disableDeadlines,
		identityAwareProxyOAuthClient: iappb.NewIdentityAwareProxyOAuthServiceClient(connPool),
		CallOptions:                   &client.CallOptions,
	}
	c.setGoogleClientInfo()

	client.internalClient = c

	return &client, nil
}

// Connection returns a connection to the API service.
//
// Deprecated.
func (c *identityAwareProxyOAuthGRPCClient) Connection() *grpc.ClientConn {
	return c.connPool.Conn()
}

// setGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *identityAwareProxyOAuthGRPCClient) setGoogleClientInfo(keyval ...string) {
	kv := append([]string{"gl-go", versionGo()}, keyval...)
	kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version)
	c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}

// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *identityAwareProxyOAuthGRPCClient) Close() error {
	return c.connPool.Close()
}

func (c *identityAwareProxyOAuthGRPCClient) ListBrands(ctx context.Context, req *iappb.ListBrandsRequest, opts ...gax.CallOption) (*iappb.ListBrandsResponse, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).ListBrands[0:len((*c.CallOptions).ListBrands):len((*c.CallOptions).ListBrands)], opts...)
	var resp *iappb.ListBrandsResponse
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.ListBrands(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) CreateBrand(ctx context.Context, req *iappb.CreateBrandRequest, opts ...gax.CallOption) (*iappb.Brand, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).CreateBrand[0:len((*c.CallOptions).CreateBrand):len((*c.CallOptions).CreateBrand)], opts...)
	var resp *iappb.Brand
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.CreateBrand(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) GetBrand(ctx context.Context, req *iappb.GetBrandRequest, opts ...gax.CallOption) (*iappb.Brand, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).GetBrand[0:len((*c.CallOptions).GetBrand):len((*c.CallOptions).GetBrand)], opts...)
	var resp *iappb.Brand
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.GetBrand(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) CreateIdentityAwareProxyClient(ctx context.Context, req *iappb.CreateIdentityAwareProxyClientRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).CreateIdentityAwareProxyClient[0:len((*c.CallOptions).CreateIdentityAwareProxyClient):len((*c.CallOptions).CreateIdentityAwareProxyClient)], opts...)
	var resp *iappb.IdentityAwareProxyClient
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.CreateIdentityAwareProxyClient(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) ListIdentityAwareProxyClients(ctx context.Context, req *iappb.ListIdentityAwareProxyClientsRequest, opts ...gax.CallOption) *IdentityAwareProxyClientIterator {
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", url.QueryEscape(req.GetParent())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).ListIdentityAwareProxyClients[0:len((*c.CallOptions).ListIdentityAwareProxyClients):len((*c.CallOptions).ListIdentityAwareProxyClients)], opts...)
	it := &IdentityAwareProxyClientIterator{}
	req = proto.Clone(req).(*iappb.ListIdentityAwareProxyClientsRequest)
	it.InternalFetch = func(pageSize int, pageToken string) ([]*iappb.IdentityAwareProxyClient, string, error) {
		resp := &iappb.ListIdentityAwareProxyClientsResponse{}
		if pageToken != "" {
			req.PageToken = pageToken
		}
		if pageSize > math.MaxInt32 {
			req.PageSize = math.MaxInt32
		} else if pageSize != 0 {
			req.PageSize = int32(pageSize)
		}
		err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
			var err error
			resp, err = c.identityAwareProxyOAuthClient.ListIdentityAwareProxyClients(ctx, req, settings.GRPC...)
			return err
		}, opts...)
		if err != nil {
			return nil, "", err
		}

		it.Response = resp
		return resp.GetIdentityAwareProxyClients(), resp.GetNextPageToken(), nil
	}
	fetch := func(pageSize int, pageToken string) (string, error) {
		items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
		if err != nil {
			return "", err
		}
		it.items = append(it.items, items...)
		return nextPageToken, nil
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
	it.pageInfo.MaxSize = int(req.GetPageSize())
	it.pageInfo.Token = req.GetPageToken()

	return it
}

func (c *identityAwareProxyOAuthGRPCClient) GetIdentityAwareProxyClient(ctx context.Context, req *iappb.GetIdentityAwareProxyClientRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).GetIdentityAwareProxyClient[0:len((*c.CallOptions).GetIdentityAwareProxyClient):len((*c.CallOptions).GetIdentityAwareProxyClient)], opts...)
	var resp *iappb.IdentityAwareProxyClient
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.GetIdentityAwareProxyClient(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) ResetIdentityAwareProxyClientSecret(ctx context.Context, req *iappb.ResetIdentityAwareProxyClientSecretRequest, opts ...gax.CallOption) (*iappb.IdentityAwareProxyClient, error) {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).ResetIdentityAwareProxyClientSecret[0:len((*c.CallOptions).ResetIdentityAwareProxyClientSecret):len((*c.CallOptions).ResetIdentityAwareProxyClientSecret)], opts...)
	var resp *iappb.IdentityAwareProxyClient
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		resp, err = c.identityAwareProxyOAuthClient.ResetIdentityAwareProxyClientSecret(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *identityAwareProxyOAuthGRPCClient) DeleteIdentityAwareProxyClient(ctx context.Context, req *iappb.DeleteIdentityAwareProxyClientRequest, opts ...gax.CallOption) error {
	if _, ok := ctx.Deadline(); !ok && !c.disableDeadlines {
		cctx, cancel := context.WithTimeout(ctx, 60000*time.Millisecond)
		defer cancel()
		ctx = cctx
	}
	md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", url.QueryEscape(req.GetName())))

	ctx = insertMetadata(ctx, c.xGoogMetadata, md)
	opts = append((*c.CallOptions).DeleteIdentityAwareProxyClient[0:len((*c.CallOptions).DeleteIdentityAwareProxyClient):len((*c.CallOptions).DeleteIdentityAwareProxyClient)], opts...)
	err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
		var err error
		_, err = c.identityAwareProxyOAuthClient.DeleteIdentityAwareProxyClient(ctx, req, settings.GRPC...)
		return err
	}, opts...)
	return err
}

// IdentityAwareProxyClientIterator manages a stream of *iappb.IdentityAwareProxyClient.
type IdentityAwareProxyClientIterator struct {
	items    []*iappb.IdentityAwareProxyClient
	pageInfo *iterator.PageInfo
	nextFunc func() error

	// Response is the raw response for the current page.
	// It must be cast to the RPC response type.
	// Calling Next() or InternalFetch() updates this value.
	Response interface{}

	// InternalFetch is for use by the Google Cloud Libraries only.
	// It is not part of the stable interface of this package.
	//
	// InternalFetch returns results from a single call to the underlying RPC.
	// The number of results is no greater than pageSize.
	// If there are no more results, nextPageToken is empty and err is nil.
	InternalFetch func(pageSize int, pageToken string) (results []*iappb.IdentityAwareProxyClient, nextPageToken string, err error)
}

// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *IdentityAwareProxyClientIterator) PageInfo() *iterator.PageInfo {
	return it.pageInfo
}

// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *IdentityAwareProxyClientIterator) Next() (*iappb.IdentityAwareProxyClient, error) {
	var item *iappb.IdentityAwareProxyClient
	if err := it.nextFunc(); err != nil {
		return item, err
	}
	item = it.items[0]
	it.items = it.items[1:]
	return item, nil
}

func (it *IdentityAwareProxyClientIterator) bufLen() int {
	return len(it.items)
}

func (it *IdentityAwareProxyClientIterator) takeBuf() interface{} {
	b := it.items
	it.items = nil
	return b
}
