From 74654f58db1719c383fdb9fb81f6892a9a89125d Mon Sep 17 00:00:00 2001 From: Cody Oss Date: Thu, 15 Dec 2022 16:11:33 -0600 Subject: [PATCH 1/3] feat(option/internaloption): add new EmbeddableAdapter option --- option/internaloption/internaloption.go | 7 +++ .../internaloption_external_test.go | 62 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 option/internaloption/internaloption_external_test.go 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..b994712c245 --- /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 dailing. 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 +} From 7bd054c1d54559172a08eabd11ae3aca56097929 Mon Sep 17 00:00:00 2001 From: Cody Oss Date: Thu, 15 Dec 2022 16:34:07 -0600 Subject: [PATCH 2/3] calm vet down about Apply methods --- internal/kokoro/vet.sh | 1 + 1 file changed, 1 insertion(+) 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 | ( \ From dcb1f83e497aaebdb4f3382f7e536c55b5983425 Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:07:09 -0600 Subject: [PATCH 3/3] Update option/internaloption/internaloption_external_test.go Co-authored-by: Noah Dietz --- option/internaloption/internaloption_external_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/option/internaloption/internaloption_external_test.go b/option/internaloption/internaloption_external_test.go index b994712c245..f5a0a6003c5 100644 --- a/option/internaloption/internaloption_external_test.go +++ b/option/internaloption/internaloption_external_test.go @@ -45,7 +45,7 @@ func NewFoo(ctx context.Context, opts ...option.ClientOption) (*Foo, error) { fooOpt.ApplyOpt(&conf) } } - // Pass options to internals for dailing. All client specific options will + // Pass options to internals for dialing. All client-specific options will // be no-ops. return &Foo{i: conf.i}, nil }