Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(option/internaloption): add new EmbeddableAdapter option #1787

Merged
merged 3 commits into from Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/kokoro/vet.sh
Expand Up @@ -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 | ( \
Expand Down
7 changes: 7 additions & 0 deletions option/internaloption/internaloption.go
Expand Up @@ -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) {}
62 changes: 62 additions & 0 deletions 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
codyoss marked this conversation as resolved.
Show resolved Hide resolved
// 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
}