Skip to content

Commit 78e33f2

Browse files
authored
refactor!: Rename to anyutil (#101)
1 parent bd5ba28 commit 78e33f2

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

any/any.go renamed to anyutil/any.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,18 @@
2828
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31-
package any
31+
package anyutil
3232

3333
import (
34+
"fmt"
35+
"strings"
36+
3437
"google.golang.org/protobuf/proto"
38+
"google.golang.org/protobuf/reflect/protodesc"
39+
"google.golang.org/protobuf/reflect/protoreflect"
40+
"google.golang.org/protobuf/reflect/protoregistry"
3541
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
42+
"google.golang.org/protobuf/types/dynamicpb"
3643
"google.golang.org/protobuf/types/known/anypb"
3744
)
3845

@@ -61,3 +68,45 @@ func MarshalFrom(dst *anypb.Any, src proto.Message, opts proto.MarshalOptions) e
6168
dst.Value = b
6269
return nil
6370
}
71+
72+
// Unpack unpacks the message inside an any, first using the provided
73+
// typeResolver (defaults to protoregistry.GlobalTypes), and if that fails,
74+
// then using the provided fileResolver (defaults to protoregistry.GlobalFiles)
75+
// with dynamicpb.
76+
func Unpack(any *anypb.Any, fileResolver protodesc.Resolver, typeResolver protoregistry.MessageTypeResolver) (proto.Message, error) {
77+
if typeResolver == nil {
78+
typeResolver = protoregistry.GlobalTypes
79+
}
80+
81+
url := any.TypeUrl
82+
typ, err := typeResolver.FindMessageByURL(url)
83+
if err == protoregistry.NotFound {
84+
if fileResolver == nil {
85+
fileResolver = protoregistry.GlobalFiles
86+
}
87+
88+
// If the proto v2 registry doesn't have this message, then we use
89+
// protoFiles (which can e.g. be initialized to gogo's MergedRegistry)
90+
// to retrieve the message descriptor, and then use dynamicpb on that
91+
// message descriptor to create a proto.Message
92+
typeURL := strings.TrimPrefix(any.TypeUrl, "/")
93+
94+
msgDesc, err := fileResolver.FindDescriptorByName(protoreflect.FullName(typeURL))
95+
if err != nil {
96+
return nil, fmt.Errorf("protoFiles does not have descriptor %s: %w", any.TypeUrl, err)
97+
}
98+
99+
typ = dynamicpb.NewMessageType(msgDesc.(protoreflect.MessageDescriptor))
100+
101+
} else if err != nil {
102+
return nil, err
103+
}
104+
105+
packedMsg := typ.New().Interface()
106+
err = any.UnmarshalTo(packedMsg)
107+
if err != nil {
108+
return nil, fmt.Errorf("cannot unmarshal msg %s: %w", any.TypeUrl, err)
109+
}
110+
111+
return packedMsg, nil
112+
}
Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
1-
package any_test
1+
package anyutil_test
22

33
import (
44
"testing"
55

66
"github.com/google/go-cmp/cmp"
77
"github.com/stretchr/testify/require"
88
"google.golang.org/protobuf/proto"
9+
"google.golang.org/protobuf/reflect/protoregistry"
910
"google.golang.org/protobuf/testing/protocmp"
1011
"google.golang.org/protobuf/types/known/anypb"
1112

12-
"github.com/cosmos/cosmos-proto/any"
13+
"github.com/cosmos/cosmos-proto/anyutil"
1314
"github.com/cosmos/cosmos-proto/testpb"
1415
)
1516

1617
func TestAny(t *testing.T) {
1718
value := &testpb.A{SomeBoolean: true}
1819

1920
dst1 := &anypb.Any{}
20-
err := any.MarshalFrom(dst1, value, proto.MarshalOptions{})
21+
err := anyutil.MarshalFrom(dst1, value, proto.MarshalOptions{})
2122
require.NoError(t, err)
2223
require.Equal(t, "/A", dst1.TypeUrl) // Make sure there's no "type.googleapis.com/" prefix.
2324

24-
dst2, err := any.New(value)
25+
dst2, err := anyutil.New(value)
2526
require.NoError(t, err)
2627
require.Equal(t, "/A", dst2.TypeUrl) // Make sure there's no "type.googleapis.com/" prefix.
2728

@@ -31,3 +32,20 @@ func TestAny(t *testing.T) {
3132
diff := cmp.Diff(value, newValue, protocmp.Transform())
3233
require.Empty(t, diff)
3334
}
35+
36+
func TestUnpack(t *testing.T) {
37+
value := &testpb.A{SomeBoolean: true}
38+
any, err := anyutil.New(value)
39+
require.NoError(t, err)
40+
41+
msg, err := anyutil.Unpack(any, nil, nil)
42+
require.NoError(t, err)
43+
diff := cmp.Diff(value, msg, protocmp.Transform())
44+
require.Empty(t, diff)
45+
46+
// Test the same thing with using the dynamicpb path.
47+
msg, err = anyutil.Unpack(any, protoregistry.GlobalFiles, &protoregistry.Types{})
48+
require.NoError(t, err)
49+
diff = cmp.Diff(value, msg, protocmp.Transform())
50+
require.Empty(t, diff)
51+
}

any/doc.go renamed to anyutil/doc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
//
1717
// This package exposes the `New` and `MarshalFrom` helper functions, which do
1818
// not prepend any prefix to type URLs.
19-
package any
19+
package anyutil

0 commit comments

Comments
 (0)