Skip to content

Commit

Permalink
WIP wirepath changes
Browse files Browse the repository at this point in the history
  • Loading branch information
reddaly authored and gonzojive committed Oct 4, 2021
1 parent 741d429 commit 3740d46
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 30 deletions.
1 change: 0 additions & 1 deletion wirepath/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ go_test(
deps = [
"//proto/wirepath:go_default_library",
"//proto/wirepath/testproto:go_default_library",
"@com_github_golang_glog//:go_default_library",
"@com_github_google_go_cmp//cmp:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
Expand Down
18 changes: 18 additions & 0 deletions wirepath/cmpexamples/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "go_default_library",
srcs = [
"cmpexample.go",
"cmpexample2.go",
],
importpath = "github.com/google/xtoproto/wirepath/cmpexamples",
visibility = ["//visibility:private"],
deps = ["@com_github_google_go_cmp//cmp:go_default_library"],
)

go_binary(
name = "cmpexamples",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
80 changes: 80 additions & 0 deletions wirepath/cmpexamples/cmpexample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main

import (
"fmt"

"github.com/google/go-cmp/cmp"
)

type I interface {
Foo() string
}

type AlwaysA struct{}

func (a *AlwaysA) Foo() string { return "A" }

type AnotherImpl struct{ foo string }

func (b *AnotherImpl) Foo() string { return b.foo }

func main() {
transformCount := 0
transformIToString := cmp.Transformer("T", func(i I) string {
transformCount++
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
})
{
var a1, a2 interface{} = &AlwaysA{}, &AnotherImpl{"A"}
_, isA1AssignableToI := a1.(I)
_, isA2AssignableToI := a2.(I)
explainAssignability("a1", isA1AssignableToI)
explainAssignability("a2", isA2AssignableToI)

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("transform count: %d", transformCount)
}
fmt.Printf("===============================================================================\n")
{
var a1, a2 I = &AlwaysA{}, &AnotherImpl{"A"}
_, isA1AssignableToI := a1.(I)
_, isA2AssignableToI := a2.(I)
explainAssignability("a1", isA1AssignableToI)
explainAssignability("a2", isA2AssignableToI)

fmt.Printf("diff2: %s\n", cmp.Diff(a1, a2, transformIToString))
}
fmt.Printf("===============================================================================\n")
{
a1, a2 := &AlwaysA{}, &AnotherImpl{"A"}
// _, isA1AssignableToI := a1.(I)
// _, isA2AssignableToI := a2.(I)
// explainAssignability("a1", isA1AssignableToI)
// explainAssignability("a2", isA2AssignableToI)

fmt.Printf("diff3: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("diff4: %s\n", cmp.Diff(&a1, &a2, transformIToString))
}
}

func explainAssignability(name string, assignable bool) {
if assignable {
fmt.Printf("%s IS assignable to I\n", name)
return
}
fmt.Printf("%s is NOT assignable to I\n", name)
}

func explain(name string, thing interface{}) string {
_, assignable := thing.(I)
if assignable {
return fmt.Sprintf("%s IS assignable to I")
}
return fmt.Sprintf("%s is NOT assignable to I")
}

func transformIToFoo(i I) string {
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
}
47 changes: 47 additions & 0 deletions wirepath/cmpexamples/cmpexample2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"fmt"

"github.com/google/go-cmp/cmp"
)

type I interface {
Foo() string
}

type AlwaysA struct{}

func (a *AlwaysA) Foo() string { return "A" }

type AnotherImpl struct{ foo string }

func (b *AnotherImpl) Foo() string { return b.foo }

func main() {
transformCount := 0
// "The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way."
transformIToString := cmp.Transformer("T", func(i I) string {
transformCount++
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
})
var a1, a2 interface{} = &AlwaysA{}, &AnotherImpl{"A"}
_, isA1AssignableToI := a1.(I)
_, isA2AssignableToI := a2.(I)
explainAssignability("a1", isA1AssignableToI)
explainAssignability("a2", isA2AssignableToI)

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("transform count: %d\n", transformCount)
}

func explainAssignability(name string, assignable bool) {
if assignable {
fmt.Printf("%s IS assignable to I\n", name)
return
}
fmt.Printf("%s is NOT assignable to I\n", name)
}
15 changes: 15 additions & 0 deletions wirepath/cmpexamples/example2/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "go_default_library",
srcs = ["example2.go"],
importpath = "github.com/google/xtoproto/wirepath/cmpexamples/example2",
visibility = ["//visibility:private"],
deps = ["@com_github_google_go_cmp//cmp:go_default_library"],
)

go_binary(
name = "example2",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
130 changes: 130 additions & 0 deletions wirepath/cmpexamples/example2/example2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package main

import (
"fmt"
"reflect"

"github.com/google/go-cmp/cmp"
)

type I interface {
Foo() string
}

type AlwaysA struct{}

func (a *AlwaysA) Foo() string { return "A" }

type AnotherImpl struct{ foo string }

func (b *AnotherImpl) Foo() string { return b.foo }

func main() {
fmt.Printf("=============== case 1 =================\n")
case1()
fmt.Printf("=============== case 2 =================\n")
case2()
fmt.Printf("=============== case 3 =================\n")
case3()
fmt.Printf("=============== case 4 =================\n")
case4()
}

func case1() {
transformCount := 0
// "The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way."
f := func(i I) string {
transformCount++
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
}
transformIToString := cmp.Transformer("T", f)
var a1, a2 interface{} = &AlwaysA{}, &AnotherImpl{"A"}

_, isA1AssignableToI := a1.(I)
_, isA2AssignableToI := a2.(I)
explainAssignability("a1", isA1AssignableToI)
explainAssignability("a2", isA2AssignableToI)
T := reflect.ValueOf(f).Type().In(0)
explainAssignability("a1", reflect.ValueOf(a1).Type().AssignableTo(T))
explainAssignability("a2", reflect.ValueOf(a2).Type().AssignableTo(T))

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("transform count: %d\n", transformCount)
}

func case2() {
transformCount := 0
// "The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way."
f := func(i I) string {
transformCount++
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
}
transformIToString := cmp.Transformer("T", f)
type X struct{ Eye I }
var a1, a2 X = X{&AlwaysA{}}, X{&AnotherImpl{"A"}}

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("transform count: %d\n", transformCount)
}

func case3() {
transformCount := 0
// "The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way."
f := func(i I) string {
transformCount++
fmt.Printf("transformIToFoo(%+v) called, got %q\n", i, i.Foo())
return i.Foo()
}
transformIToString := cmp.Transformer("T", f)
type X struct{ Eye interface{} }
var a1, a2 X = X{&AlwaysA{}}, X{&AnotherImpl{"A"}}

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, transformIToString))
fmt.Printf("transform count: %d\n", transformCount)
}

func case4() {
transformCount := 0
// "The transformer f must be a function "func(T) R" that converts values of
// type T to those of type R and is implicitly filtered to input values
// assignable to T. The transformer must not mutate T in any way."
f := func(i interface{}) string {
transformCount++
return i.(I).Foo()
}
opt := cmp.FilterValues(func(x, y interface{}) bool {
_, ok1 := x.(I)
_, ok2 := y.(I)
return ok1 && ok2
}, cmp.Transformer("T", f))
var a1, a2 interface{} = &AlwaysA{}, &AnotherImpl{"B"}

fmt.Printf("diff1: %s\n", cmp.Diff(a1, a2, opt))
fmt.Printf("transform count: %d\n", transformCount)
}

func explainAssignability(name string, assignable bool) {
if assignable {
fmt.Printf("%s IS assignable to I\n", name)
return
}
fmt.Printf("%s is NOT assignable to I\n", name)
}

func explainAssignabilityUsingReflection(name string, v reflect.Value) {
iReflectType := reflect.ValueOf(func(I) {}).Type().In(0)
assignable := v.Type().AssignableTo(iReflectType)
if assignable {
fmt.Printf("%s IS assignable to %v\n", name, iReflectType)
return
}
fmt.Printf("%s is NOT assignable to %v\n", name, iReflectType)
}
Loading

0 comments on commit 3740d46

Please sign in to comment.