FLEXProtocolBuilder.m 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // FLEXProtocolBuilder.m
  3. // FLEX
  4. //
  5. // Derived from MirrorKit.
  6. // Created by Tanner on 7/4/15.
  7. // Copyright (c) 2015 Tanner Bennett. All rights reserved.
  8. //
  9. #import "FLEXProtocolBuilder.h"
  10. #import "FLEXProtocol.h"
  11. #import "FLEXProperty.h"
  12. #import <objc/runtime.h>
  13. #define MutationAssertion(msg) if (self.isRegistered) { \
  14. [NSException \
  15. raise:NSInternalInconsistencyException \
  16. format:msg \
  17. ]; \
  18. }
  19. @interface FLEXProtocolBuilder ()
  20. @property (nonatomic) Protocol *workingProtocol;
  21. @property (nonatomic) NSString *name;
  22. @end
  23. @implementation FLEXProtocolBuilder
  24. - (id)init {
  25. [NSException
  26. raise:NSInternalInconsistencyException
  27. format:@"Class instance should not be created with -init"
  28. ];
  29. return nil;
  30. }
  31. #pragma mark Initializers
  32. + (instancetype)allocateProtocol:(NSString *)name {
  33. NSParameterAssert(name);
  34. return [[self alloc] initWithProtocol:objc_allocateProtocol(name.UTF8String)];
  35. }
  36. - (id)initWithProtocol:(Protocol *)protocol {
  37. NSParameterAssert(protocol);
  38. self = [super init];
  39. if (self) {
  40. _workingProtocol = protocol;
  41. _name = NSStringFromProtocol(self.workingProtocol);
  42. }
  43. return self;
  44. }
  45. - (NSString *)description {
  46. return [NSString stringWithFormat:@"<%@ name=%@, registered=%d>",
  47. NSStringFromClass(self.class), self.name, self.isRegistered];
  48. }
  49. #pragma mark Building
  50. - (void)addProperty:(FLEXProperty *)property isRequired:(BOOL)isRequired {
  51. MutationAssertion(@"Properties cannot be added once a protocol has been registered");
  52. unsigned int count;
  53. objc_property_attribute_t *attributes = [property copyAttributesList:&count];
  54. protocol_addProperty(self.workingProtocol, property.name.UTF8String, attributes, count, isRequired, YES);
  55. free(attributes);
  56. }
  57. - (void)addMethod:(SEL)selector
  58. typeEncoding:(NSString *)typeEncoding
  59. isRequired:(BOOL)isRequired
  60. isInstanceMethod:(BOOL)isInstanceMethod {
  61. MutationAssertion(@"Methods cannot be added once a protocol has been registered");
  62. protocol_addMethodDescription(self.workingProtocol, selector, typeEncoding.UTF8String, isRequired, isInstanceMethod);
  63. }
  64. - (void)addProtocol:(Protocol *)protocol {
  65. MutationAssertion(@"Protocols cannot be added once a protocol has been registered");
  66. protocol_addProtocol(self.workingProtocol, protocol);
  67. }
  68. - (FLEXProtocol *)registerProtocol {
  69. MutationAssertion(@"Protocol is already registered");
  70. _isRegistered = YES;
  71. objc_registerProtocol(self.workingProtocol);
  72. return [FLEXProtocol protocol:self.workingProtocol];
  73. }
  74. @end