From 1569e5b294ad150050319c108bfbcade2180351b Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Thu, 15 Dec 2022 23:20:14 +0000 Subject: [PATCH] feat(option/internaloption): add new EmbeddableAdapter option (#1787) --- internal/kokoro/vet.sh | 1 + option/internaloption/internaloption.go | 7 +++ .../internaloption_external_test.go | 62 +++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 option/internaloption/internaloption_external_test.go diff --git a/internal/kokoro/vet.sh b/internal/kokoro/vet.sh index 3fd7f754da8..dd5c45c793c 100755 --- a/internal/kokoro/vet.sh +++ b/internal/kokoro/vet.sh @@ -37,6 +37,7 @@ golint ./... 2>&1 | ( \ grep -v "exported method MarshalStyle.JSONReader should have comment or be unexported" | \ grep -v "UnmarshalJSON should have comment or be unexported" | \ grep -v "MarshalJSON should have comment or be unexported" | \ + grep -v ".Apply should have comment or be unexported" | \ grep -vE "\.pb\.go:" || true) | tee /dev/stderr | (! read) staticcheck -go 1.9 ./... 2>&1 | ( \ diff --git a/option/internaloption/internaloption.go b/option/internaloption/internaloption.go index 343a5a965eb..cc7ebfe277b 100644 --- a/option/internaloption/internaloption.go +++ b/option/internaloption/internaloption.go @@ -134,3 +134,10 @@ type withCreds google.Credentials func (w *withCreds) Apply(o *internal.DialSettings) { o.InternalCredentials = (*google.Credentials)(w) } + +// EmbeddableAdapter is a no-op option.ClientOption that allow libraries to +// create their own client options by embedding this type into their own +// client-specific option wrapper. See example for usage. +type EmbeddableAdapter struct{} + +func (*EmbeddableAdapter) Apply(_ *internal.DialSettings) {} diff --git a/option/internaloption/internaloption_external_test.go b/option/internaloption/internaloption_external_test.go new file mode 100644 index 00000000000..f5a0a6003c5 --- /dev/null +++ b/option/internaloption/internaloption_external_test.go @@ -0,0 +1,62 @@ +// Copyright 2022 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internaloption_test + +import ( + "context" + "fmt" + + "google.golang.org/api/option" + "google.golang.org/api/option/internaloption" +) + +type config struct { + i int +} + +type clientSpecificOption interface { + option.ClientOption + ApplyOpt(*config) +} + +func WithFavoriteNumber(i int) option.ClientOption { + return &withFavoriteNumber{i: i} +} + +type withFavoriteNumber struct { + internaloption.EmbeddableAdapter + i int +} + +func (w *withFavoriteNumber) ApplyOpt(c *config) { + c.i = w.i +} + +type Foo struct { + i int +} + +func NewFoo(ctx context.Context, opts ...option.ClientOption) (*Foo, error) { + var conf config + for _, opt := range opts { + if fooOpt, ok := opt.(clientSpecificOption); ok { + fooOpt.ApplyOpt(&conf) + } + } + // Pass options to internals for dialing. All client-specific options will + // be no-ops. + return &Foo{i: conf.i}, nil +} + +func (f *Foo) Number() int { return f.i } + +func ExampleEmbeddableAdapter() { + f, err := NewFoo(context.Background(), WithFavoriteNumber(42)) + if err != nil { + // TODO: handle error + } + fmt.Println(f.Number()) + // Output: 42 +}