Commit 1647e63c authored by Paul Yang's avatar Paul Yang

Merge pull request #602 from TeBoring/objectivec

Add packTo and unpackFrom in google.protobuf.Any.
parents 353b7a99 7366efd8
......@@ -27,7 +27,6 @@ __EOF__
fi
cd src
make $@ google/protobuf/stubs/pbconfig.h
declare -a RUNTIME_PROTO_FILES=(\
google/protobuf/any.proto \
......
......@@ -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
......@@ -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
......@@ -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
......@@ -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=(\
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment