Преглед на файлове

Merge pull request #602 from TeBoring/objectivec

Add packTo and unpackFrom in google.protobuf.Any.
Paul Yang преди 10 години
родител
ревизия
1647e63c57

+ 0 - 1
generate_descriptor_proto.sh

@@ -27,7 +27,6 @@ __EOF__
 fi
 
 cd src
-make $@ google/protobuf/stubs/pbconfig.h
 
 declare -a RUNTIME_PROTO_FILES=(\
   google/protobuf/any.proto \

+ 21 - 1
objectivec/GPBWellKnownTypes.h

@@ -30,8 +30,10 @@
 
 #import <Foundation/Foundation.h>
 
-#import "google/protobuf/Timestamp.pbobjc.h"
+#import "google/protobuf/Any.pbobjc.h"
 #import "google/protobuf/Duration.pbobjc.h"
+#import "google/protobuf/Timestamp.pbobjc.h"
+
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -49,4 +51,22 @@ NS_ASSUME_NONNULL_BEGIN
 - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
 @end
 
+// Extension to GPBAny to support packing and unpacking for arbitrary messages.
+@interface GPBAny (GPBWellKnownTypes)
+// Initialize GPBAny instance with the given message. e.g., for google.protobuf.foo, type
+// url will be "type.googleapis.com/google.protobuf.foo" and value will be serialized foo.
+- (instancetype)initWithMessage:(GPBMessage*)message;
+// Serialize the given message to the value in GPBAny. Type url will also be updated.
+- (void)setMessage:(GPBMessage*)message;
+// Parse the value in GPBAny to the given message. If messageClass message doesn't match the
+// type url in GPBAny, nil is returned.
+- (GPBMessage*)messageOfClass:(Class)messageClass;
+// True if the given type matches the type url in GPBAny.
+- (BOOL)wrapsMessageOfClass:(Class)messageClass;
+@end
+
+// Common prefix of type url in GPBAny, which is @"type.googleapis.com/". All valid
+// type urls in any should start with this prefix.
+extern NSString *const GPBTypeGoogleApisComPrefix;
+
 NS_ASSUME_NONNULL_END

+ 49 - 0
objectivec/GPBWellKnownTypes.m

@@ -115,3 +115,52 @@ static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
 }
 
 @end
+
+NSString *const GPBTypeGoogleApisComPrefix = @"type.googleapis.com/";
+
+@implementation GPBAny (GBPWellKnownTypes)
+
+- (instancetype)initWithMessage:(GPBMessage*)message {
+  self = [super init];
+  if (self) {
+    [self setMessage:message];
+  }
+  return self;
+}
+
+- (NSString*)typeName {
+  NSAssert([self.typeURL hasPrefix:GPBTypeGoogleApisComPrefix],
+           @"Invalid any type url (%@).", self.typeURL);
+  if (![self.typeURL hasPrefix:GPBTypeGoogleApisComPrefix]) {
+    return nil;
+  }
+  return [self.typeURL substringFromIndex:[GPBTypeGoogleApisComPrefix length]];
+}
+
+- (void)setMessage:(GPBMessage*)message {
+  self.typeURL = [GPBTypeGoogleApisComPrefix stringByAppendingString:message.descriptor.name];
+  self.value = message.data;
+}
+
+- (GPBMessage*)messageOfClass:(Class)messageClass {
+  if ([self wrapsMessageOfClass:messageClass]) {
+    GPBMessage* message = [messageClass message];
+    [message mergeFromData:self.value extensionRegistry:nil];
+    return message;
+  } else {
+    return nil;
+  }
+}
+
+- (BOOL)wrapsMessageOfClass:(Class)messageClass {
+  NSAssert([messageClass isSubclassofClass:[GPBMessage class]],
+           @"Given class (%@) is not a subclass of GPBMessage",
+           [messageClass name]);
+  if (![messageClass isSubclassOfClass:[GPBMessage class]]) {
+    return NO;
+  }
+  return [[self typeName] isEqualToString:messageClass.descriptor.name];
+}
+
+@end
+

+ 52 - 1
objectivec/Tests/GPBWellKnownTypesTest.m

@@ -28,7 +28,9 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#import "google/protobuf/Unittest.pbobjc.h"
 #import "GPBWellKnownTypes.h"
+#import "GPBTestUtilities.h"
 
 #import <XCTest/XCTest.h>
 
@@ -38,7 +40,7 @@ static const NSTimeInterval kFutureOffsetInterval = 15000;
 // Nanosecond time accuracy
 static const NSTimeInterval kTimeAccuracy = 1e-9;
 
-@interface WellKnownTypesTest : XCTestCase
+@interface WellKnownTypesTest : GPBTestCase
 @end
 
 @implementation WellKnownTypesTest
@@ -99,4 +101,53 @@ static const NSTimeInterval kTimeAccuracy = 1e-9;
   [duration2 release];
 }
 
+- (void)testAnyPackingAndUnpacking {
+  TestAllTypes *from = [TestAllTypes message];
+  [self setAllFields:from repeatedCount:1];
+  NSData *data = from.data;
+
+  // Test initWithMessage
+  GPBAny *anyInited = [[GPBAny alloc] initWithMessage:from];
+  XCTAssertEqualObjects(
+      [GPBTypeGoogleApisComPrefix stringByAppendingString:from.descriptor.name],
+      anyInited.typeURL);
+  XCTAssertEqualObjects(data, anyInited.value);
+  [anyInited release];
+
+  // Test setMessage.
+  GPBAny *any = [GPBAny message];
+  [any setMessage:from];
+  XCTAssertEqualObjects(
+      [GPBTypeGoogleApisComPrefix stringByAppendingString:from.descriptor.name],
+      any.typeURL);
+  XCTAssertEqualObjects(data, any.value);
+
+  // Test messageOfClass
+  TestAllTypes *to = (TestAllTypes*)[any messageOfClass:[TestAllTypes class]];
+  XCTAssertEqualObjects(from, to);
+  XCTAssertEqual([any messageOfClass:[ForeignMessage class]], nil);
+  XCTAssertEqual([[GPBAny message] messageOfClass:[TestAllTypes class]], nil);
+
+  // Test setMessage with another type.
+  ForeignMessage *from2 = [ForeignMessage message];
+  [any setMessage:from2];
+  XCTAssertEqualObjects(
+      [GPBTypeGoogleApisComPrefix stringByAppendingString:from2.descriptor.name],
+      any.typeURL);
+  XCTAssertEqual(0UL, [any.value length]);
+
+  // Test wrapsMessageOfClass
+  XCTAssertTrue([any wrapsMessageOfClass:[from2 class]]);
+  XCTAssertFalse([any wrapsMessageOfClass:[from class]]);
+#if !defined(NS_BLOCK_ASSERTIONS)
+  // If assert is enabled, throw exception when the passed message class to
+  // wrapsMessageOfClass is not a child of GPBMessage.
+  XCTAssertThrows([any wrapsMessageOfClass:[NSString class]]);
+#else
+  // If assert is disabled, return false when the passed message class to
+  // wrapsMessageOfClass is not a child of GPBMessage.
+  XCTAssertFalse([any wrapsMessageOfClass:[NSString class]]);
+#endif
+}
+
 @end

+ 0 - 1
objectivec/generate_descriptors_proto.sh

@@ -33,7 +33,6 @@ fi
 
 # Make sure the compiler is current.
 cd src
-make $@ google/protobuf/stubs/pbconfig.h
 make $@ protoc
 
 declare -a RUNTIME_PROTO_FILES=(\