From bdf8b0112928f3bb8b72627dbd46235dc22dbb73 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Tue, 30 Aug 2016 08:55:04 -0700 Subject: core,protobuf: Add simple argument introspection for methods The cast required in protobuf makes me question how much I like ReflectableMarshaller, but it seems to be pretty sound and the cast is more an artifact of generics than the API. Nano and Thrift were purposefully not updated, since getting just the class requires making a new message instance. That seems a bit lame. It probably is no burden to create an instance to get the class, and it may not be too hard to improve the factory to provide class information, but didn't want to bother at this point. Especially since nano users are unlikely to need the introspection functionality. --- .../main/java/io/grpc/protobuf/lite/ProtoLiteUtils.java | 16 +++++++++++++++- .../java/io/grpc/protobuf/lite/ProtoLiteUtilsTest.java | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'protobuf-lite') diff --git a/protobuf-lite/src/main/java/io/grpc/protobuf/lite/ProtoLiteUtils.java b/protobuf-lite/src/main/java/io/grpc/protobuf/lite/ProtoLiteUtils.java index a66f57b5a..9742a7672 100644 --- a/protobuf-lite/src/main/java/io/grpc/protobuf/lite/ProtoLiteUtils.java +++ b/protobuf-lite/src/main/java/io/grpc/protobuf/lite/ProtoLiteUtils.java @@ -43,6 +43,7 @@ import io.grpc.ExperimentalApi; import io.grpc.KnownLength; import io.grpc.Metadata; import io.grpc.MethodDescriptor.Marshaller; +import io.grpc.MethodDescriptor.PrototypeMarshaller; import io.grpc.Status; import io.grpc.internal.GrpcUtil; @@ -81,7 +82,20 @@ public class ProtoLiteUtils { public static Marshaller marshaller(final T defaultInstance) { @SuppressWarnings("unchecked") final Parser parser = (Parser) defaultInstance.getParserForType(); - return new Marshaller() { + // TODO(ejona): consider changing return type to PrototypeMarshaller (assuming ABI safe) + return new PrototypeMarshaller() { + @SuppressWarnings("unchecked") + @Override + public Class getMessageClass() { + // Precisely T since protobuf doesn't let messages extend other messages. + return (Class) defaultInstance.getClass(); + } + + @Override + public T getMessagePrototype() { + return defaultInstance; + } + @Override public InputStream stream(T value) { return new ProtoInputStream(value, parser); diff --git a/protobuf-lite/src/test/java/io/grpc/protobuf/lite/ProtoLiteUtilsTest.java b/protobuf-lite/src/test/java/io/grpc/protobuf/lite/ProtoLiteUtilsTest.java index 53809deeb..612300006 100644 --- a/protobuf-lite/src/test/java/io/grpc/protobuf/lite/ProtoLiteUtilsTest.java +++ b/protobuf-lite/src/test/java/io/grpc/protobuf/lite/ProtoLiteUtilsTest.java @@ -47,6 +47,7 @@ import com.google.protobuf.Type; import io.grpc.Drainable; import io.grpc.Metadata; import io.grpc.MethodDescriptor.Marshaller; +import io.grpc.MethodDescriptor.PrototypeMarshaller; import io.grpc.Status; import io.grpc.StatusRuntimeException; @@ -118,6 +119,14 @@ public class ProtoLiteUtilsTest { assertEquals(proto, marshaller.parse(enumMarshaller.stream(altProto))); } + @Test + public void introspection() throws Exception { + Marshaller enumMarshaller = ProtoLiteUtils.marshaller(Enum.getDefaultInstance()); + PrototypeMarshaller prototypeMarshaller = (PrototypeMarshaller) enumMarshaller; + assertSame(Enum.getDefaultInstance(), prototypeMarshaller.getMessagePrototype()); + assertSame(Enum.class, prototypeMarshaller.getMessageClass()); + } + @Test public void marshallerShouldNotLimitProtoSize() throws Exception { // The default limit is 64MB. Using a larger proto to verify that the limit is not enforced. -- cgit v1.2.3