func (p *PerRPCCreds) Apply(c *Client) {
	c.creds = p.Creds
}
Apply saves the per-RPC creds in the Client.
package client
import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"strings"
	"time"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/actas"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/balancer"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/chunker"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/digest"
	"github.com/bazelbuild/remote-apis-sdks/go/pkg/retry"
	"github.com/pkg/errors"
	"golang.org/x/oauth2"
	"golang.org/x/sync/semaphore"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/oauth"
	"google.golang.org/grpc/status"
	configpb "github.com/bazelbuild/remote-apis-sdks/go/pkg/balancer/proto"
	regrpc "github.com/bazelbuild/remote-apis/build/bazel/remote/execution/v2"
	repb "github.com/bazelbuild/remote-apis/build/bazel/remote/execution/v2"
	log "github.com/golang/glog"
	emptypb "github.com/golang/protobuf/ptypes/empty"
	bsgrpc "google.golang.org/genproto/googleapis/bytestream"
	bspb "google.golang.org/genproto/googleapis/bytestream"
	opgrpc "google.golang.org/genproto/googleapis/longrunning"
	oppb "google.golang.org/genproto/googleapis/longrunning"
)
const (
	scopes = "https://www.googleapis.com/auth/cloud-platform"
	HomeDirMacro = "${HOME}"
)
type Client struct {
	InstanceName string
	actionCache  regrpc.ActionCacheClient
	byteStream   bsgrpc.ByteStreamClient
	cas          regrpc.ContentAddressableStorageClient
	execution    regrpc.ExecutionClient
	operations   opgrpc.OperationsClient
	Retrier       *Retrier
	Connection    *grpc.ClientConn
	CASConnection *grpc.ClientConn  
	StartupCapabilities StartupCapabilities
	ChunkMaxSize ChunkMaxSize
	CompressedBytestreamThreshold CompressedBytestreamThreshold
	MaxBatchDigests MaxBatchDigests
	MaxBatchSize MaxBatchSize
	DirMode os.FileMode
	ExecutableMode os.FileMode
	RegularMode os.FileMode
	UtilizeLocality UtilizeLocality
	UnifiedUploads UnifiedUploads
	UnifiedUploadBufferSize UnifiedUploadBufferSize
	UnifiedUploadTickDuration UnifiedUploadTickDuration
	UnifiedDownloads UnifiedDownloads
	UnifiedDownloadBufferSize UnifiedDownloadBufferSize
	UnifiedDownloadTickDuration UnifiedDownloadTickDuration
	TreeSymlinkOpts     *TreeSymlinkOpts
	serverCaps          *repb.ServerCapabilities
	useBatchOps         UseBatchOps
	casConcurrency      int64
	casUploaders        *semaphore.Weighted
	casUploadRequests   chan *uploadRequest
	casUploads          map[digest.Digest]*uploadState
	casDownloaders      *semaphore.Weighted
	casDownloadRequests chan *downloadRequest
	rpcTimeouts         RPCTimeouts
	creds               credentials.PerRPCCredentials
}
const (
	DefaultMaxBatchSize = 4*1024*1024 - 1024
	DefaultMaxBatchDigests = 4000
	DefaultDirMode = 0777
	DefaultExecutableMode = 0777
	DefaultRegularMode = 0644
)
func (c *Client) Close() error {
	UnifiedUploads(false).Apply(c)
	UnifiedDownloads(false).Apply(c)
	err := c.Connection.Close()
	if err != nil {
		return err
	}
	if c.CASConnection != c.Connection {
		return c.CASConnection.Close()
	}
	return nil
}
type Opt interface {
	Apply(*Client)
}
type ChunkMaxSize int
func (s ChunkMaxSize) Apply(c *Client) {
	c.ChunkMaxSize = s
}
type CompressedBytestreamThreshold int64
func (s CompressedBytestreamThreshold) Apply(c *Client) {
	c.CompressedBytestreamThreshold = s
}
type UtilizeLocality bool
func (s UtilizeLocality) Apply(c *Client) {
	c.UtilizeLocality = s
}
type UnifiedUploads bool
func (c *Client) restartUploader() {
	if c.casUploadRequests == nil {
		return
	}
	close(c.casUploadRequests)
	c.casUploadRequests = make(chan *uploadRequest, c.UnifiedUploadBufferSize)
	go c.uploadProcessor()
}
func (c *Client) restartDownloader() {
	if c.casDownloadRequests == nil {
		return
	}
	close(c.casDownloadRequests)
	c.casDownloadRequests = make(chan *downloadRequest, c.UnifiedDownloadBufferSize)
	go c.downloadProcessor()
}
func (s UnifiedUploads) Apply(c *Client) {
	if c.UnifiedUploads == s {
		return
	}
	if s {
		c.casUploadRequests = make(chan *uploadRequest, c.UnifiedUploadBufferSize)
		go c.uploadProcessor()
	} else {
		close(c.casUploadRequests)
	}
	c.UnifiedUploads = s
}
type UnifiedUploadBufferSize int
const DefaultUnifiedUploadBufferSize = 10000
func (s UnifiedUploadBufferSize) Apply(c *Client) {
	if c.UnifiedUploadBufferSize != s {
		c.UnifiedUploadBufferSize = s
		c.restartUploader()
	}
}
type UnifiedUploadTickDuration time.Duration
const DefaultUnifiedUploadTickDuration = UnifiedUploadTickDuration(50 * time.Millisecond)
func (s UnifiedUploadTickDuration) Apply(c *Client) {
	if c.UnifiedUploadTickDuration != s {
		c.UnifiedUploadTickDuration = s
		c.restartUploader()
	}
}
type UnifiedDownloads bool
func (s UnifiedDownloads) Apply(c *Client) {
	if c.UnifiedDownloads == s {
		return
	}
	if s {
		c.casDownloadRequests = make(chan *downloadRequest, c.UnifiedDownloadBufferSize)
		go c.downloadProcessor()
	} else {
		close(c.casDownloadRequests)
	}
	c.UnifiedDownloads = s
}
type UnifiedDownloadBufferSize int
const DefaultUnifiedDownloadBufferSize = 10000
func (s UnifiedDownloadBufferSize) Apply(c *Client) {
	if c.UnifiedDownloadBufferSize != s {
		c.UnifiedDownloadBufferSize = s
		c.restartDownloader()
	}
}
type UnifiedDownloadTickDuration time.Duration
const DefaultUnifiedDownloadTickDuration = UnifiedDownloadTickDuration(50 * time.Millisecond)
func (s UnifiedDownloadTickDuration) Apply(c *Client) {
	if c.UnifiedDownloadTickDuration != s {
		c.UnifiedDownloadTickDuration = s
		c.restartDownloader()
	}
}
func (o *TreeSymlinkOpts) Apply(c *Client) {
	c.TreeSymlinkOpts = o
}
type MaxBatchDigests int
func (s MaxBatchDigests) Apply(c *Client) {
	c.MaxBatchDigests = s
}
type MaxBatchSize int64
func (s MaxBatchSize) Apply(c *Client) {
	c.MaxBatchSize = s
}
type DirMode os.FileMode
func (m DirMode) Apply(c *Client) {
	c.DirMode = os.FileMode(m)
}
type ExecutableMode os.FileMode
func (m ExecutableMode) Apply(c *Client) {
	c.ExecutableMode = os.FileMode(m)
}
type RegularMode os.FileMode
func (m RegularMode) Apply(c *Client) {
	c.RegularMode = os.FileMode(m)
}
type UseBatchOps bool
func (u UseBatchOps) Apply(c *Client) {
	c.useBatchOps = u
}
type CASConcurrency int
const DefaultCASConcurrency = 500
const DefaultMaxConcurrentRequests = 25
const DefaultMaxConcurrentStreams = 25
func (cy CASConcurrency) Apply(c *Client) {
	c.casConcurrency = int64(cy)
	c.casUploaders = semaphore.NewWeighted(c.casConcurrency)
	c.casDownloaders = semaphore.NewWeighted(c.casConcurrency)
}
type StartupCapabilities bool
func (s StartupCapabilities) Apply(c *Client) {
	c.StartupCapabilities = s
}
type PerRPCCreds struct {
	Creds credentials.PerRPCCredentials
}