From 64c99988a7c1d99ef37b9fd337868263c3d81c16 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 1 Aug 2018 14:37:09 -0400 Subject: [PATCH] Code generate Swift wrappers for protocol buffers. --- Scripts/ProtoWrappers.py | 271 ++- SignalServiceKit/protobuf/SignalService.proto | 24 + .../src/Protos/Generated/SSKProto.swift | 1976 +++++++++++++++-- .../Protos/Generated/SignalService.pb.swift | 24 + 4 files changed, 2103 insertions(+), 192 deletions(-) diff --git a/Scripts/ProtoWrappers.py b/Scripts/ProtoWrappers.py index e774f6be7..a71a8669f 100755 --- a/Scripts/ProtoWrappers.py +++ b/Scripts/ProtoWrappers.py @@ -196,15 +196,22 @@ class BaseContext(object): return base_type def can_field_be_optional(self, field): - if field.proto_type == 'uint64': - return False - elif field.proto_type == 'uint32': - return False - elif field.proto_type == 'fixed64': - return False - elif field.proto_type == 'bool': - return False - elif self.is_field_an_enum(field): + if field.proto_type in ('uint64', + 'uint32', + 'fixed64', + 'bool', ): + return not field.is_required + + # if field.proto_type == 'uint64': + # return False + # elif field.proto_type == 'uint32': + # return False + # elif field.proto_type == 'fixed64': + # return False + # elif field.proto_type == 'bool': + # return False + # elif self.is_field_an_enum(field): + if self.is_field_an_enum(field): return False else: return True @@ -293,15 +300,23 @@ public enum %s: Error { class MessageField: - def __init__(self, name, index, rules, proto_type, default_value, sort_index): + def __init__(self, name, index, rules, proto_type, default_value, sort_index, is_required): self.name = name self.index = index self.rules = rules self.proto_type = proto_type self.default_value = default_value self.sort_index = sort_index + self.is_required = is_required - + def has_accessor_name(self): + name = 'has' + self.name_swift[0].upper() + self.name_swift[1:] + if name == 'hasId': + # TODO: I'm not sure why "Apple Swift Proto" code formats the + # the name in this way. + name = 'hasID' + return name + class MessageContext(BaseContext): def __init__(self, args, parent, proto_name): BaseContext.__init__(self) @@ -339,7 +354,7 @@ class MessageContext(BaseContext): def generate(self, writer): for child in self.messages: child.generate(writer) - + writer.add('// MARK: - %s' % self.swift_name) writer.newline() @@ -351,10 +366,17 @@ class MessageContext(BaseContext): for child in self.enums: child.generate(writer) + wrapped_swift_name = self.derive_wrapped_swift_name() + # Prepare fields for field in self.fields(): field.type_swift = self.swift_type_for_field(field) field.name_swift = lowerCamlCaseForUnderscoredText_wrapped(field.name) + + self.generate_builder(writer) + + # writer.add('private let proto: %s' % wrapped_swift_name ) + # writer.newline() # Property Declarations for field in self.fields(): @@ -388,7 +410,6 @@ public func serializedData() throws -> Data { writer.newline() # parseData() func - wrapped_swift_name = self.derive_wrapped_swift_name() writer.add('@objc public class func parseData(_ serializedData: Data) throws -> %s {' % self.swift_name) writer.push_indent() writer.add('let proto = try %s(serializedData: serializedData)' % ( wrapped_swift_name, ) ) @@ -402,6 +423,25 @@ public func serializedData() throws -> Data { writer.push_indent() for field in self.fields(): + if field.is_required: + # if self.can_field_be_optional(field): + writer.add('guard proto.%s else {' % field.has_accessor_name() ) + writer.push_indent() + writer.add('throw %s.invalidProtobuf(description: "\(logTag) missing required field: %s")' % ( writer.invalid_protobuf_error_name, field.name_swift, ) ) + writer.pop_indent() + writer.add('}') + + if self.is_field_an_enum(field): + # TODO: Assert that rules is empty. + enum_context = self.context_for_proto_type(field) + writer.add('let %s = %sWrap(proto.%s)' % ( field.name_swift, enum_context.swift_name, field.name_swift, ) ) + elif self.is_field_a_proto(field): + writer.add('let %s = try %s.parseProto(proto.%s)' % (field.name_swift, self.base_swift_type_for_field(field), field.name_swift)), + else: + writer.add('let %s = proto.%s' % ( field.name_swift, field.name_swift, ) ) + writer.newline() + continue + default_value = self.default_value_for_field(field) if default_value is None: writer.add('var %s: %s' % (field.name_swift, field.type_swift)) @@ -421,12 +461,7 @@ public func serializedData() throws -> Data { writer.add('let wrapped = item') writer.add('%s.append(wrapped)' % ( field.name_swift, ) ) else: - hasAccessor = 'has' + field.name_swift[0].upper() + field.name_swift[1:] - if hasAccessor == 'hasId': - # TODO: I'm not sure why "Apple Swift Proto" code formats the - # the name in this way. - hasAccessor = 'hasID' - writer.add('if proto.%s {' % hasAccessor) + writer.add('if proto.%s {' % field.has_accessor_name() ) writer.push_indent() if self.is_field_an_enum(field): @@ -526,7 +561,140 @@ public func serializedData() throws -> Data { writer.add('}') writer.newline() + def generate_builder(self, writer): + + wrapped_swift_name = self.derive_wrapped_swift_name() + writer.add('// MARK: - %sBuilder' % self.swift_name) + writer.newline() + + writer.add('@objc public class %sBuilder: NSObject {' % self.swift_name) + writer.newline() + + writer.push_context(self.proto_name, self.swift_name) + + wrapped_swift_name = self.derive_wrapped_swift_name() + + # Property Declarations + for field in self.fields(): + if field.rules == 'repeated': + writer.add('private var %s: [%s]' % ( field.name_swift, self.base_swift_type_for_field(field), )) + else: + writer.add('private var %s: %s?' % ( field.name_swift, self.base_swift_type_for_field(field), )) + writer.newline() + + # Initializer + writer.add('@objc public override init() {}') + writer.newline() + + # Setters + for field in self.fields(): + if field.rules == 'repeated': + accessor_name = field.name_swift + accessor_name = 'add' + accessor_name[0].upper() + accessor_name[1:] + writer.add('@objc public func %s(_ value: %s) {' % ( accessor_name, self.base_swift_type_for_field(field), )) + writer.push_indent() + writer.add('%s.append(value)' % ( field.name_swift, ) ) + writer.pop_indent() + writer.add('}') + writer.newline() + else: + accessor_name = field.name_swift + accessor_name = 'set' + accessor_name[0].upper() + accessor_name[1:] + writer.add('@objc public func %s(_ value: %s) {' % ( accessor_name, self.base_swift_type_for_field(field), )) + writer.push_indent() + writer.add('%s = value' % ( field.name_swift, ) ) + writer.pop_indent() + writer.add('}') + writer.newline() + + # build() func + writer.add('@objc public func build() throws -> %s {' % self.swift_name) + writer.push_indent() + writer.add('let proto = %s.with { (builder) in' % wrapped_swift_name) + writer.push_indent() + for field in self.fields(): + if field.rules == 'repeated': + accessor_name = field.name_swift + accessor_name = 'add' + accessor_name[0].upper() + accessor_name[1:] + + writer.add('for item in %s {' % (field.name_swift)) + writer.push_indent() + if self.is_field_an_enum(field): + enum_context = self.context_for_proto_type(field) + writer.add('builder.%s(%sUnwrap(item))' % ( accessor_name, enum_context.swift_name, ) ) + elif self.is_field_a_proto(field): + writer.add('builder.%s(item.asProtobuf)' % accessor_name) + else: + writer.add('builder.%s(item)' % accessor_name) + writer.pop_indent() + writer.add('}') + else: + writer.add('if let %s = self.%s {' % ( field.name_swift, field.name_swift, )) + writer.push_indent() + if self.is_field_an_enum(field): + enum_context = self.context_for_proto_type(field) + writer.add('builder.%s = %sUnwrap(%s)' % ( field.name_swift, enum_context.swift_name, field.name_swift, ) ) + elif self.is_field_a_proto(field): + writer.add('builder.%s = %s.asProtobuf' % ( field.name_swift, field.name_swift, ) ) + else: + writer.add('builder.%s = %s' % ( field.name_swift, field.name_swift, ) ) + writer.pop_indent() + writer.add('}') + + # if self.is_field_an_enum(field): + # # TODO: Assert that rules is empty. + # enum_context = self.context_for_proto_type(field) + # writer.add('builder.%s = %s.%sUnwrap(self.%s)' % ( field.name_swift, self.swift_name, enum_context.swift_name, field.name_swift, ) ) + # elif field.rules == 'repeated': + # # TODO: Assert that type is a message. + # list_wrapped_swift_name = None + # if self.is_field_a_proto(field): + # message_context = self.context_for_proto_type(field) + # list_wrapped_swift_name = message_context.derive_wrapped_swift_name() + # else: + # # TODO: Assert not an enum. + # list_wrapped_swift_name = self.base_swift_type_for_field(field) + # writer.add('var %sUnwrapped = [%s]()' % (field.name_swift, list_wrapped_swift_name)) + # writer.add('for item in %s {' % (field.name_swift)) + # writer.push_indent() + # if self.is_field_a_proto(field): + # writer.add('%sUnwrapped.append(item.asProtobuf)' % field.name_swift) + # else: + # writer.add('%sUnwrapped.append(item)' % field.name_swift) + # writer.pop_indent() + # writer.add('}') + # writer.add('builder.%s = %sUnwrapped' % (field.name_swift, field.name_swift)) + # elif field.rules == 'optional' and self.can_field_be_optional(field): + # writer.add('if let %s = self.%s {' % (field.name_swift, field.name_swift)) + # writer.push_indent() + # if self.is_field_a_proto(field): + # writer.add('builder.%s = %s.asProtobuf' % (field.name_swift, field.name_swift)) + # else: + # writer.add('builder.%s = %s' % (field.name_swift, field.name_swift)) + # writer.pop_indent() + # writer.add('}') + # else: + # writer.add('builder.%s = self.%s' % (field.name_swift, field.name_swift)) + # writer.newline() + # writer.add('self.%s = %s' % (field.name_swift, field.name_swift)) + writer.rstrip() + writer.pop_indent() + writer.add('}') + writer.newline() + # writer.add('let protoData = try proto.serializedData()') + writer.add('let wrapper = try %s.parseProto(proto)' % self.swift_name) + writer.add('return wrapper') + writer.pop_indent() + writer.add('}') + writer.newline() + + writer.pop_context() + + writer.rstrip() + writer.add('}') + writer.newline() + class EnumContext(BaseContext): def __init__(self, args, parent, proto_name): BaseContext.__init__(self) @@ -613,25 +781,42 @@ class EnumContext(BaseContext): writer.add('}') writer.newline() - -def line_parser(text): - # lineParser = LineParser(text.split('\n')) + +class LineParser: + def __init__(self, text): + self.lines = text.split('\n') + self.lines.reverse() + self.next_line_comments = [] - for line in text.split('\n'): - line = line.strip() - # if not line: - # continue + def next(self): + # lineParser = LineParser(text.split('\n')) + + self.next_line_comments = [] + while len(self.lines) > 0: + line = self.lines.pop() + line = line.strip() + # if not line: + # continue - comment_index = line.find('//') - if comment_index >= 0: - line = line[:comment_index].strip() - if not line: - continue + comment_index = line.find('//') + if comment_index >= 0: + comment = line[comment_index + len('//'):].strip() + line = line[:comment_index].strip() + if not line: + if comment: + self.next_line_comments.append(comment) + else: + if not line: + self.next_line_comments = [] + + if not line: + continue - if args.verbose: - print 'line:', line + # if args.verbose: + # print 'line:', line - yield line + return line + raise StopIteration() def parse_enum(args, proto_file_path, parser, parent_context, enum_name): @@ -648,8 +833,8 @@ def parse_enum(args, proto_file_path, parser, parent_context, enum_name): raise Exception('Incomplete enum: %s' % proto_file_path) if line == '}': - if args.verbose: - print + # if args.verbose: + # print parent_context.enums.append(context) return @@ -696,9 +881,11 @@ def parse_message(args, proto_file_path, parser, parent_context, message_name): except StopIteration: raise Exception('Incomplete message: %s' % proto_file_path) + field_comments = parser.next_line_comments + if line == '}': - if args.verbose: - print + # if args.verbose: + # print parent_context.messages.append(context) return @@ -743,6 +930,7 @@ def parse_message(args, proto_file_path, parser, parent_context, message_name): 'name': item_name, 'index': item_index, 'default': item_default, + 'field_comments': field_comments, } # print 'message_field:', message_field @@ -757,7 +945,10 @@ def parse_message(args, proto_file_path, parser, parent_context, message_name): raise Exception('Duplicate message field index[%s]: %s' % (proto_file_path, item_name)) # context.field_indices.add(item_index) - context.field_map[item_index] = MessageField(item_name, item_index, item_rules, item_type, item_default, sort_index) + is_required = '@required' in field_comments + # if is_required: + # print 'is_required:', item_name + context.field_map[item_index] = MessageField(item_name, item_index, item_rules, item_type, item_default, sort_index, is_required) sort_index = sort_index + 1 @@ -815,7 +1006,7 @@ def process_proto_file(args, proto_file_path, dst_file_path): package_regex = re.compile(r'^package\s+(.+);') option_regex = re.compile(r'^option ') - parser = line_parser(text) + parser = LineParser(text) # lineParser = LineParser(text.split('\n')) diff --git a/SignalServiceKit/protobuf/SignalService.proto b/SignalServiceKit/protobuf/SignalService.proto index 83cce0616..f71a6d0d7 100644 --- a/SignalServiceKit/protobuf/SignalService.proto +++ b/SignalServiceKit/protobuf/SignalService.proto @@ -23,10 +23,14 @@ message Envelope { RECEIPT = 5; } + // @required optional Type type = 1; + // @required optional string source = 2; + // @required optional uint32 sourceDevice = 7; optional string relay = 3; + // @required optional uint64 timestamp = 5; optional bytes legacyMessage = 6; // Contains an encrypted DataMessage optional bytes content = 8; // Contains an encrypted Content @@ -42,6 +46,7 @@ message Content { message CallMessage { message Offer { + // @required optional uint64 id = 1; // Signal-iOS renamed the description field to avoid // conflicts with [NSObject description]. @@ -49,6 +54,7 @@ message CallMessage { } message Answer { + // @required optional uint64 id = 1; // Signal-iOS renamed the description field to avoid // conflicts with [NSObject description]. @@ -56,6 +62,7 @@ message CallMessage { } message IceUpdate { + // @required optional uint64 id = 1; optional string sdpMid = 2; optional uint32 sdpMLineIndex = 3; @@ -63,10 +70,12 @@ message CallMessage { } message Busy { + // @required optional uint64 id = 1; } message Hangup { + // @required optional uint64 id = 1; } @@ -100,7 +109,9 @@ message DataMessage { optional uint32 flags = 4; } + // @required optional uint64 id = 1; + // @required optional string author = 2; optional string text = 3; repeated QuotedAttachment attachments = 4; @@ -124,6 +135,7 @@ message DataMessage { CUSTOM = 4; } + // @required optional string value = 1; optional Type type = 2; optional string label = 3; @@ -137,6 +149,7 @@ message DataMessage { CUSTOM = 4; } + // @required optional string value = 1; optional Type type = 2; optional string label = 3; @@ -194,6 +207,7 @@ message ReceiptMessage { READ = 1; } + // @required optional Type type = 1; repeated uint64 timestamp = 2; } @@ -205,6 +219,7 @@ message Verified { UNVERIFIED = 2; } + // @required optional string destination = 1; optional bytes identityKey = 2; optional State state = 3; @@ -220,6 +235,7 @@ message SyncMessage { } message Contacts { + // @required optional AttachmentPointer blob = 1; // Signal-iOS renamed this property. optional bool isComplete = 2 [default = false]; @@ -242,11 +258,14 @@ message SyncMessage { CONFIGURATION = 4; } + // @required optional Type type = 1; } message Read { + // @required optional string sender = 1; + // @required optional uint64 timestamp = 2; } @@ -270,6 +289,7 @@ message AttachmentPointer { VOICE_MESSAGE = 1; } + // @required optional fixed64 id = 1; optional string contentType = 2; optional bytes key = 3; @@ -290,7 +310,9 @@ message GroupContext { QUIT = 3; REQUEST_INFO = 4; } + // @required optional bytes id = 1; + // @required optional Type type = 2; optional string name = 3; repeated string members = 4; @@ -303,6 +325,7 @@ message ContactDetails { optional uint32 length = 2; } + // @required optional string number = 1; optional string name = 2; optional Avatar avatar = 3; @@ -319,6 +342,7 @@ message GroupDetails { optional uint32 length = 2; } + // @required optional bytes id = 1; optional string name = 2; repeated string members = 3; diff --git a/SignalServiceKit/src/Protos/Generated/SSKProto.swift b/SignalServiceKit/src/Protos/Generated/SSKProto.swift index 059e75cf9..1e543ed11 100644 --- a/SignalServiceKit/src/Protos/Generated/SSKProto.swift +++ b/SignalServiceKit/src/Protos/Generated/SSKProto.swift @@ -44,6 +44,78 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoEnvelopeBuilder + + @objc public class SSKProtoEnvelopeBuilder: NSObject { + + private var type: SSKProtoEnvelopeType? + private var source: String? + private var sourceDevice: UInt32? + private var relay: String? + private var timestamp: UInt64? + private var legacyMessage: Data? + private var content: Data? + + @objc public override init() {} + + @objc public func setType(_ value: SSKProtoEnvelopeType) { + type = value + } + + @objc public func setSource(_ value: String) { + source = value + } + + @objc public func setSourceDevice(_ value: UInt32) { + sourceDevice = value + } + + @objc public func setRelay(_ value: String) { + relay = value + } + + @objc public func setTimestamp(_ value: UInt64) { + timestamp = value + } + + @objc public func setLegacyMessage(_ value: Data) { + legacyMessage = value + } + + @objc public func setContent(_ value: Data) { + content = value + } + + @objc public func build() throws -> SSKProtoEnvelope { + let proto = SignalServiceProtos_Envelope.with { (builder) in + if let type = self.type { + builder.type = SSKProtoEnvelopeTypeUnwrap(type) + } + if let source = self.source { + builder.source = source + } + if let sourceDevice = self.sourceDevice { + builder.sourceDevice = sourceDevice + } + if let relay = self.relay { + builder.relay = relay + } + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } + if let legacyMessage = self.legacyMessage { + builder.legacyMessage = legacyMessage + } + if let content = self.content { + builder.content = content + } + } + + let wrapper = try SSKProtoEnvelope.parseProto(proto) + return wrapper + } + } + @objc public let type: SSKProtoEnvelopeType @objc public let source: String? @objc public let sourceDevice: UInt32 @@ -79,30 +151,30 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_Envelope) throws -> SSKProtoEnvelope { - var type: SSKProtoEnvelopeType = .unknown - if proto.hasType { - type = SSKProtoEnvelopeTypeWrap(proto.type) + guard proto.hasType else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: type") } + let type = SSKProtoEnvelopeTypeWrap(proto.type) - var source: String? = nil - if proto.hasSource { - source = proto.source + guard proto.hasSource else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: source") } + let source = proto.source - var sourceDevice: UInt32 = 0 - if proto.hasSourceDevice { - sourceDevice = proto.sourceDevice + guard proto.hasSourceDevice else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: sourceDevice") } + let sourceDevice = proto.sourceDevice var relay: String? = nil if proto.hasRelay { relay = proto.relay } - var timestamp: UInt64 = 0 - if proto.hasTimestamp { - timestamp = proto.timestamp + guard proto.hasTimestamp else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: timestamp") } + let timestamp = proto.timestamp var legacyMessage: Data? = nil if proto.hasLegacyMessage { @@ -174,6 +246,62 @@ public enum SSKProtoError: Error { @objc public class SSKProtoContent: NSObject { + // MARK: - SSKProtoContentBuilder + + @objc public class SSKProtoContentBuilder: NSObject { + + private var dataMessage: SSKProtoDataMessage? + private var syncMessage: SSKProtoSyncMessage? + private var callMessage: SSKProtoCallMessage? + private var nullMessage: SSKProtoNullMessage? + private var receiptMessage: SSKProtoReceiptMessage? + + @objc public override init() {} + + @objc public func setDataMessage(_ value: SSKProtoDataMessage) { + dataMessage = value + } + + @objc public func setSyncMessage(_ value: SSKProtoSyncMessage) { + syncMessage = value + } + + @objc public func setCallMessage(_ value: SSKProtoCallMessage) { + callMessage = value + } + + @objc public func setNullMessage(_ value: SSKProtoNullMessage) { + nullMessage = value + } + + @objc public func setReceiptMessage(_ value: SSKProtoReceiptMessage) { + receiptMessage = value + } + + @objc public func build() throws -> SSKProtoContent { + let proto = SignalServiceProtos_Content.with { (builder) in + if let dataMessage = self.dataMessage { + builder.dataMessage = dataMessage.asProtobuf + } + if let syncMessage = self.syncMessage { + builder.syncMessage = syncMessage.asProtobuf + } + if let callMessage = self.callMessage { + builder.callMessage = callMessage.asProtobuf + } + if let nullMessage = self.nullMessage { + builder.nullMessage = nullMessage.asProtobuf + } + if let receiptMessage = self.receiptMessage { + builder.receiptMessage = receiptMessage.asProtobuf + } + } + + let wrapper = try SSKProtoContent.parseProto(proto) + return wrapper + } + } + @objc public let dataMessage: SSKProtoDataMessage? @objc public let syncMessage: SSKProtoSyncMessage? @objc public let callMessage: SSKProtoCallMessage? @@ -271,6 +399,38 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessageOffer: NSObject { + // MARK: - SSKProtoCallMessageOfferBuilder + + @objc public class SSKProtoCallMessageOfferBuilder: NSObject { + + private var id: UInt64? + private var sessionDescription: String? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func setSessionDescription(_ value: String) { + sessionDescription = value + } + + @objc public func build() throws -> SSKProtoCallMessageOffer { + let proto = SignalServiceProtos_CallMessage.Offer.with { (builder) in + if let id = self.id { + builder.id = id + } + if let sessionDescription = self.sessionDescription { + builder.sessionDescription = sessionDescription + } + } + + let wrapper = try SSKProtoCallMessageOffer.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public let sessionDescription: String? @@ -291,10 +451,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_CallMessage.Offer) throws -> SSKProtoCallMessageOffer { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id var sessionDescription: String? = nil if proto.hasSessionDescription { @@ -327,6 +487,38 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessageAnswer: NSObject { + // MARK: - SSKProtoCallMessageAnswerBuilder + + @objc public class SSKProtoCallMessageAnswerBuilder: NSObject { + + private var id: UInt64? + private var sessionDescription: String? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func setSessionDescription(_ value: String) { + sessionDescription = value + } + + @objc public func build() throws -> SSKProtoCallMessageAnswer { + let proto = SignalServiceProtos_CallMessage.Answer.with { (builder) in + if let id = self.id { + builder.id = id + } + if let sessionDescription = self.sessionDescription { + builder.sessionDescription = sessionDescription + } + } + + let wrapper = try SSKProtoCallMessageAnswer.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public let sessionDescription: String? @@ -347,10 +539,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_CallMessage.Answer) throws -> SSKProtoCallMessageAnswer { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id var sessionDescription: String? = nil if proto.hasSessionDescription { @@ -383,14 +575,62 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessageIceUpdate: NSObject { + // MARK: - SSKProtoCallMessageIceUpdateBuilder + + @objc public class SSKProtoCallMessageIceUpdateBuilder: NSObject { + + private var id: UInt64? + private var sdpMid: String? + private var sdpMlineIndex: UInt32? + private var sdp: String? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func setSdpMid(_ value: String) { + sdpMid = value + } + + @objc public func setSdpMlineIndex(_ value: UInt32) { + sdpMlineIndex = value + } + + @objc public func setSdp(_ value: String) { + sdp = value + } + + @objc public func build() throws -> SSKProtoCallMessageIceUpdate { + let proto = SignalServiceProtos_CallMessage.IceUpdate.with { (builder) in + if let id = self.id { + builder.id = id + } + if let sdpMid = self.sdpMid { + builder.sdpMid = sdpMid + } + if let sdpMlineIndex = self.sdpMlineIndex { + builder.sdpMlineIndex = sdpMlineIndex + } + if let sdp = self.sdp { + builder.sdp = sdp + } + } + + let wrapper = try SSKProtoCallMessageIceUpdate.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public let sdpMid: String? - @objc public let sdpMlineIndex: UInt32 + @objc public let sdpMlineIndex: UInt32? @objc public let sdp: String? @objc public init(id: UInt64, sdpMid: String?, - sdpMlineIndex: UInt32, + sdpMlineIndex: UInt32?, sdp: String?) { self.id = id self.sdpMid = sdpMid @@ -409,17 +649,17 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_CallMessage.IceUpdate) throws -> SSKProtoCallMessageIceUpdate { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id var sdpMid: String? = nil if proto.hasSdpMid { sdpMid = proto.sdpMid } - var sdpMlineIndex: UInt32 = 0 + var sdpMlineIndex: UInt32? = nil if proto.hasSdpMlineIndex { sdpMlineIndex = proto.sdpMlineIndex } @@ -448,7 +688,9 @@ public enum SSKProtoError: Error { builder.sdpMid = sdpMid } - builder.sdpMlineIndex = self.sdpMlineIndex + if let sdpMlineIndex = self.sdpMlineIndex { + builder.sdpMlineIndex = sdpMlineIndex + } if let sdp = self.sdp { builder.sdp = sdp @@ -463,6 +705,30 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessageBusy: NSObject { + // MARK: - SSKProtoCallMessageBusyBuilder + + @objc public class SSKProtoCallMessageBusyBuilder: NSObject { + + private var id: UInt64? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func build() throws -> SSKProtoCallMessageBusy { + let proto = SignalServiceProtos_CallMessage.Busy.with { (builder) in + if let id = self.id { + builder.id = id + } + } + + let wrapper = try SSKProtoCallMessageBusy.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public init(id: UInt64) { @@ -480,10 +746,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_CallMessage.Busy) throws -> SSKProtoCallMessageBusy { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id // MARK: - Begin Validation Logic for SSKProtoCallMessageBusy - @@ -506,6 +772,30 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessageHangup: NSObject { + // MARK: - SSKProtoCallMessageHangupBuilder + + @objc public class SSKProtoCallMessageHangupBuilder: NSObject { + + private var id: UInt64? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func build() throws -> SSKProtoCallMessageHangup { + let proto = SignalServiceProtos_CallMessage.Hangup.with { (builder) in + if let id = self.id { + builder.id = id + } + } + + let wrapper = try SSKProtoCallMessageHangup.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public init(id: UInt64) { @@ -523,10 +813,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_CallMessage.Hangup) throws -> SSKProtoCallMessageHangup { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id // MARK: - Begin Validation Logic for SSKProtoCallMessageHangup - @@ -549,6 +839,70 @@ public enum SSKProtoError: Error { @objc public class SSKProtoCallMessage: NSObject { + // MARK: - SSKProtoCallMessageBuilder + + @objc public class SSKProtoCallMessageBuilder: NSObject { + + private var offer: SSKProtoCallMessageOffer? + private var answer: SSKProtoCallMessageAnswer? + private var iceUpdate: [SSKProtoCallMessageIceUpdate] + private var hangup: SSKProtoCallMessageHangup? + private var busy: SSKProtoCallMessageBusy? + private var profileKey: Data? + + @objc public override init() {} + + @objc public func setOffer(_ value: SSKProtoCallMessageOffer) { + offer = value + } + + @objc public func setAnswer(_ value: SSKProtoCallMessageAnswer) { + answer = value + } + + @objc public func addIceUpdate(_ value: SSKProtoCallMessageIceUpdate) { + iceUpdate.append(value) + } + + @objc public func setHangup(_ value: SSKProtoCallMessageHangup) { + hangup = value + } + + @objc public func setBusy(_ value: SSKProtoCallMessageBusy) { + busy = value + } + + @objc public func setProfileKey(_ value: Data) { + profileKey = value + } + + @objc public func build() throws -> SSKProtoCallMessage { + let proto = SignalServiceProtos_CallMessage.with { (builder) in + if let offer = self.offer { + builder.offer = offer.asProtobuf + } + if let answer = self.answer { + builder.answer = answer.asProtobuf + } + for item in iceUpdate { + builder.addIceUpdate(item.asProtobuf) + } + if let hangup = self.hangup { + builder.hangup = hangup.asProtobuf + } + if let busy = self.busy { + builder.busy = busy.asProtobuf + } + if let profileKey = self.profileKey { + builder.profileKey = profileKey + } + } + + let wrapper = try SSKProtoCallMessage.parseProto(proto) + return wrapper + } + } + @objc public let offer: SSKProtoCallMessageOffer? @objc public let answer: SSKProtoCallMessageAnswer? @objc public let iceUpdate: [SSKProtoCallMessageIceUpdate] @@ -680,15 +1034,63 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoDataMessageQuoteQuotedAttachmentBuilder + + @objc public class SSKProtoDataMessageQuoteQuotedAttachmentBuilder: NSObject { + + private var contentType: String? + private var fileName: String? + private var thumbnail: SSKProtoAttachmentPointer? + private var flags: UInt32? + + @objc public override init() {} + + @objc public func setContentType(_ value: String) { + contentType = value + } + + @objc public func setFileName(_ value: String) { + fileName = value + } + + @objc public func setThumbnail(_ value: SSKProtoAttachmentPointer) { + thumbnail = value + } + + @objc public func setFlags(_ value: UInt32) { + flags = value + } + + @objc public func build() throws -> SSKProtoDataMessageQuoteQuotedAttachment { + let proto = SignalServiceProtos_DataMessage.Quote.QuotedAttachment.with { (builder) in + if let contentType = self.contentType { + builder.contentType = contentType + } + if let fileName = self.fileName { + builder.fileName = fileName + } + if let thumbnail = self.thumbnail { + builder.thumbnail = thumbnail.asProtobuf + } + if let flags = self.flags { + builder.flags = flags + } + } + + let wrapper = try SSKProtoDataMessageQuoteQuotedAttachment.parseProto(proto) + return wrapper + } + } + @objc public let contentType: String? @objc public let fileName: String? @objc public let thumbnail: SSKProtoAttachmentPointer? - @objc public let flags: UInt32 + @objc public let flags: UInt32? @objc public init(contentType: String?, fileName: String?, thumbnail: SSKProtoAttachmentPointer?, - flags: UInt32) { + flags: UInt32?) { self.contentType = contentType self.fileName = fileName self.thumbnail = thumbnail @@ -721,7 +1123,7 @@ public enum SSKProtoError: Error { thumbnail = try SSKProtoAttachmentPointer.parseProto(proto.thumbnail) } - var flags: UInt32 = 0 + var flags: UInt32? = nil if proto.hasFlags { flags = proto.flags } @@ -751,7 +1153,9 @@ public enum SSKProtoError: Error { builder.thumbnail = thumbnail.asProtobuf } - builder.flags = self.flags + if let flags = self.flags { + builder.flags = flags + } } return proto @@ -762,6 +1166,54 @@ public enum SSKProtoError: Error { @objc public class SSKProtoDataMessageQuote: NSObject { + // MARK: - SSKProtoDataMessageQuoteBuilder + + @objc public class SSKProtoDataMessageQuoteBuilder: NSObject { + + private var id: UInt64? + private var author: String? + private var text: String? + private var attachments: [SSKProtoDataMessageQuoteQuotedAttachment] + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func setAuthor(_ value: String) { + author = value + } + + @objc public func setText(_ value: String) { + text = value + } + + @objc public func addAttachments(_ value: SSKProtoDataMessageQuoteQuotedAttachment) { + attachments.append(value) + } + + @objc public func build() throws -> SSKProtoDataMessageQuote { + let proto = SignalServiceProtos_DataMessage.Quote.with { (builder) in + if let id = self.id { + builder.id = id + } + if let author = self.author { + builder.author = author + } + if let text = self.text { + builder.text = text + } + for item in attachments { + builder.addAttachments(item.asProtobuf) + } + } + + let wrapper = try SSKProtoDataMessageQuote.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public let author: String? @objc public let text: String? @@ -788,15 +1240,15 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_DataMessage.Quote) throws -> SSKProtoDataMessageQuote { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id - var author: String? = nil - if proto.hasAuthor { - author = proto.author + guard proto.hasAuthor else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: author") } + let author = proto.author var text: String? = nil if proto.hasText { @@ -847,6 +1299,70 @@ public enum SSKProtoError: Error { @objc public class SSKProtoDataMessageContactName: NSObject { + // MARK: - SSKProtoDataMessageContactNameBuilder + + @objc public class SSKProtoDataMessageContactNameBuilder: NSObject { + + private var givenName: String? + private var familyName: String? + private var prefix: String? + private var suffix: String? + private var middleName: String? + private var displayName: String? + + @objc public override init() {} + + @objc public func setGivenName(_ value: String) { + givenName = value + } + + @objc public func setFamilyName(_ value: String) { + familyName = value + } + + @objc public func setPrefix(_ value: String) { + prefix = value + } + + @objc public func setSuffix(_ value: String) { + suffix = value + } + + @objc public func setMiddleName(_ value: String) { + middleName = value + } + + @objc public func setDisplayName(_ value: String) { + displayName = value + } + + @objc public func build() throws -> SSKProtoDataMessageContactName { + let proto = SignalServiceProtos_DataMessage.Contact.Name.with { (builder) in + if let givenName = self.givenName { + builder.givenName = givenName + } + if let familyName = self.familyName { + builder.familyName = familyName + } + if let prefix = self.prefix { + builder.prefix = prefix + } + if let suffix = self.suffix { + builder.suffix = suffix + } + if let middleName = self.middleName { + builder.middleName = middleName + } + if let displayName = self.displayName { + builder.displayName = displayName + } + } + + let wrapper = try SSKProtoDataMessageContactName.parseProto(proto) + return wrapper + } + } + @objc public let givenName: String? @objc public let familyName: String? @objc public let prefix: String? @@ -984,6 +1500,46 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoDataMessageContactPhoneBuilder + + @objc public class SSKProtoDataMessageContactPhoneBuilder: NSObject { + + private var value: String? + private var type: SSKProtoDataMessageContactPhoneType? + private var label: String? + + @objc public override init() {} + + @objc public func setValue(_ value: String) { + value = value + } + + @objc public func setType(_ value: SSKProtoDataMessageContactPhoneType) { + type = value + } + + @objc public func setLabel(_ value: String) { + label = value + } + + @objc public func build() throws -> SSKProtoDataMessageContactPhone { + let proto = SignalServiceProtos_DataMessage.Contact.Phone.with { (builder) in + if let value = self.value { + builder.value = value + } + if let type = self.type { + builder.type = SSKProtoDataMessageContactPhoneTypeUnwrap(type) + } + if let label = self.label { + builder.label = label + } + } + + let wrapper = try SSKProtoDataMessageContactPhone.parseProto(proto) + return wrapper + } + } + @objc public let value: String? @objc public let type: SSKProtoDataMessageContactPhoneType @objc public let label: String? @@ -1007,10 +1563,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_DataMessage.Contact.Phone) throws -> SSKProtoDataMessageContactPhone { - var value: String? = nil - if proto.hasValue { - value = proto.value + guard proto.hasValue else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: value") } + let value = proto.value var type: SSKProtoDataMessageContactPhoneType = .home if proto.hasType { @@ -1084,6 +1640,46 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoDataMessageContactEmailBuilder + + @objc public class SSKProtoDataMessageContactEmailBuilder: NSObject { + + private var value: String? + private var type: SSKProtoDataMessageContactEmailType? + private var label: String? + + @objc public override init() {} + + @objc public func setValue(_ value: String) { + value = value + } + + @objc public func setType(_ value: SSKProtoDataMessageContactEmailType) { + type = value + } + + @objc public func setLabel(_ value: String) { + label = value + } + + @objc public func build() throws -> SSKProtoDataMessageContactEmail { + let proto = SignalServiceProtos_DataMessage.Contact.Email.with { (builder) in + if let value = self.value { + builder.value = value + } + if let type = self.type { + builder.type = SSKProtoDataMessageContactEmailTypeUnwrap(type) + } + if let label = self.label { + builder.label = label + } + } + + let wrapper = try SSKProtoDataMessageContactEmail.parseProto(proto) + return wrapper + } + } + @objc public let value: String? @objc public let type: SSKProtoDataMessageContactEmailType @objc public let label: String? @@ -1107,10 +1703,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_DataMessage.Contact.Email) throws -> SSKProtoDataMessageContactEmail { - var value: String? = nil - if proto.hasValue { - value = proto.value + guard proto.hasValue else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: value") } + let value = proto.value var type: SSKProtoDataMessageContactEmailType = .home if proto.hasType { @@ -1181,6 +1777,94 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoDataMessageContactPostalAddressBuilder + + @objc public class SSKProtoDataMessageContactPostalAddressBuilder: NSObject { + + private var type: SSKProtoDataMessageContactPostalAddressType? + private var label: String? + private var street: String? + private var pobox: String? + private var neighborhood: String? + private var city: String? + private var region: String? + private var postcode: String? + private var country: String? + + @objc public override init() {} + + @objc public func setType(_ value: SSKProtoDataMessageContactPostalAddressType) { + type = value + } + + @objc public func setLabel(_ value: String) { + label = value + } + + @objc public func setStreet(_ value: String) { + street = value + } + + @objc public func setPobox(_ value: String) { + pobox = value + } + + @objc public func setNeighborhood(_ value: String) { + neighborhood = value + } + + @objc public func setCity(_ value: String) { + city = value + } + + @objc public func setRegion(_ value: String) { + region = value + } + + @objc public func setPostcode(_ value: String) { + postcode = value + } + + @objc public func setCountry(_ value: String) { + country = value + } + + @objc public func build() throws -> SSKProtoDataMessageContactPostalAddress { + let proto = SignalServiceProtos_DataMessage.Contact.PostalAddress.with { (builder) in + if let type = self.type { + builder.type = SSKProtoDataMessageContactPostalAddressTypeUnwrap(type) + } + if let label = self.label { + builder.label = label + } + if let street = self.street { + builder.street = street + } + if let pobox = self.pobox { + builder.pobox = pobox + } + if let neighborhood = self.neighborhood { + builder.neighborhood = neighborhood + } + if let city = self.city { + builder.city = city + } + if let region = self.region { + builder.region = region + } + if let postcode = self.postcode { + builder.postcode = postcode + } + if let country = self.country { + builder.country = country + } + } + + let wrapper = try SSKProtoDataMessageContactPostalAddress.parseProto(proto) + return wrapper + } + } + @objc public let type: SSKProtoDataMessageContactPostalAddressType @objc public let label: String? @objc public let street: String? @@ -1328,11 +2012,43 @@ public enum SSKProtoError: Error { @objc public class SSKProtoDataMessageContactAvatar: NSObject { + // MARK: - SSKProtoDataMessageContactAvatarBuilder + + @objc public class SSKProtoDataMessageContactAvatarBuilder: NSObject { + + private var avatar: SSKProtoAttachmentPointer? + private var isProfile: Bool? + + @objc public override init() {} + + @objc public func setAvatar(_ value: SSKProtoAttachmentPointer) { + avatar = value + } + + @objc public func setIsProfile(_ value: Bool) { + isProfile = value + } + + @objc public func build() throws -> SSKProtoDataMessageContactAvatar { + let proto = SignalServiceProtos_DataMessage.Contact.Avatar.with { (builder) in + if let avatar = self.avatar { + builder.avatar = avatar.asProtobuf + } + if let isProfile = self.isProfile { + builder.isProfile = isProfile + } + } + + let wrapper = try SSKProtoDataMessageContactAvatar.parseProto(proto) + return wrapper + } + } + @objc public let avatar: SSKProtoAttachmentPointer? - @objc public let isProfile: Bool + @objc public let isProfile: Bool? @objc public init(avatar: SSKProtoAttachmentPointer?, - isProfile: Bool) { + isProfile: Bool?) { self.avatar = avatar self.isProfile = isProfile } @@ -1353,7 +2069,7 @@ public enum SSKProtoError: Error { avatar = try SSKProtoAttachmentPointer.parseProto(proto.avatar) } - var isProfile: Bool = false + var isProfile: Bool? = nil if proto.hasIsProfile { isProfile = proto.isProfile } @@ -1373,7 +2089,9 @@ public enum SSKProtoError: Error { builder.avatar = avatar.asProtobuf } - builder.isProfile = self.isProfile + if let isProfile = self.isProfile { + builder.isProfile = isProfile + } } return proto @@ -1384,6 +2102,70 @@ public enum SSKProtoError: Error { @objc public class SSKProtoDataMessageContact: NSObject { + // MARK: - SSKProtoDataMessageContactBuilder + + @objc public class SSKProtoDataMessageContactBuilder: NSObject { + + private var name: SSKProtoDataMessageContactName? + private var number: [SSKProtoDataMessageContactPhone] + private var email: [SSKProtoDataMessageContactEmail] + private var address: [SSKProtoDataMessageContactPostalAddress] + private var avatar: SSKProtoDataMessageContactAvatar? + private var organization: String? + + @objc public override init() {} + + @objc public func setName(_ value: SSKProtoDataMessageContactName) { + name = value + } + + @objc public func addNumber(_ value: SSKProtoDataMessageContactPhone) { + number.append(value) + } + + @objc public func addEmail(_ value: SSKProtoDataMessageContactEmail) { + email.append(value) + } + + @objc public func addAddress(_ value: SSKProtoDataMessageContactPostalAddress) { + address.append(value) + } + + @objc public func setAvatar(_ value: SSKProtoDataMessageContactAvatar) { + avatar = value + } + + @objc public func setOrganization(_ value: String) { + organization = value + } + + @objc public func build() throws -> SSKProtoDataMessageContact { + let proto = SignalServiceProtos_DataMessage.Contact.with { (builder) in + if let name = self.name { + builder.name = name.asProtobuf + } + for item in number { + builder.addNumber(item.asProtobuf) + } + for item in email { + builder.addEmail(item.asProtobuf) + } + for item in address { + builder.addAddress(item.asProtobuf) + } + if let avatar = self.avatar { + builder.avatar = avatar.asProtobuf + } + if let organization = self.organization { + builder.organization = organization + } + } + + let wrapper = try SSKProtoDataMessageContact.parseProto(proto) + return wrapper + } + } + @objc public let name: SSKProtoDataMessageContactName? @objc public let number: [SSKProtoDataMessageContactPhone] @objc public let email: [SSKProtoDataMessageContactEmail] @@ -1527,23 +2309,111 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoDataMessageBuilder + + @objc public class SSKProtoDataMessageBuilder: NSObject { + + private var body: String? + private var attachments: [SSKProtoAttachmentPointer] + private var group: SSKProtoGroupContext? + private var flags: UInt32? + private var expireTimer: UInt32? + private var profileKey: Data? + private var timestamp: UInt64? + private var quote: SSKProtoDataMessageQuote? + private var contact: [SSKProtoDataMessageContact] + + @objc public override init() {} + + @objc public func setBody(_ value: String) { + body = value + } + + @objc public func addAttachments(_ value: SSKProtoAttachmentPointer) { + attachments.append(value) + } + + @objc public func setGroup(_ value: SSKProtoGroupContext) { + group = value + } + + @objc public func setFlags(_ value: UInt32) { + flags = value + } + + @objc public func setExpireTimer(_ value: UInt32) { + expireTimer = value + } + + @objc public func setProfileKey(_ value: Data) { + profileKey = value + } + + @objc public func setTimestamp(_ value: UInt64) { + timestamp = value + } + + @objc public func setQuote(_ value: SSKProtoDataMessageQuote) { + quote = value + } + + @objc public func addContact(_ value: SSKProtoDataMessageContact) { + contact.append(value) + } + + @objc public func build() throws -> SSKProtoDataMessage { + let proto = SignalServiceProtos_DataMessage.with { (builder) in + if let body = self.body { + builder.body = body + } + for item in attachments { + builder.addAttachments(item.asProtobuf) + } + if let group = self.group { + builder.group = group.asProtobuf + } + if let flags = self.flags { + builder.flags = flags + } + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } + if let profileKey = self.profileKey { + builder.profileKey = profileKey + } + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } + if let quote = self.quote { + builder.quote = quote.asProtobuf + } + for item in contact { + builder.addContact(item.asProtobuf) + } + } + + let wrapper = try SSKProtoDataMessage.parseProto(proto) + return wrapper + } + } + @objc public let body: String? @objc public let attachments: [SSKProtoAttachmentPointer] @objc public let group: SSKProtoGroupContext? - @objc public let flags: UInt32 - @objc public let expireTimer: UInt32 + @objc public let flags: UInt32? + @objc public let expireTimer: UInt32? @objc public let profileKey: Data? - @objc public let timestamp: UInt64 + @objc public let timestamp: UInt64? @objc public let quote: SSKProtoDataMessageQuote? @objc public let contact: [SSKProtoDataMessageContact] @objc public init(body: String?, attachments: [SSKProtoAttachmentPointer], group: SSKProtoGroupContext?, - flags: UInt32, - expireTimer: UInt32, + flags: UInt32?, + expireTimer: UInt32?, profileKey: Data?, - timestamp: UInt64, + timestamp: UInt64?, quote: SSKProtoDataMessageQuote?, contact: [SSKProtoDataMessageContact]) { self.body = body @@ -1584,12 +2454,12 @@ public enum SSKProtoError: Error { group = try SSKProtoGroupContext.parseProto(proto.group) } - var flags: UInt32 = 0 + var flags: UInt32? = nil if proto.hasFlags { flags = proto.flags } - var expireTimer: UInt32 = 0 + var expireTimer: UInt32? = nil if proto.hasExpireTimer { expireTimer = proto.expireTimer } @@ -1599,7 +2469,7 @@ public enum SSKProtoError: Error { profileKey = proto.profileKey } - var timestamp: UInt64 = 0 + var timestamp: UInt64? = nil if proto.hasTimestamp { timestamp = proto.timestamp } @@ -1647,15 +2517,21 @@ public enum SSKProtoError: Error { builder.group = group.asProtobuf } - builder.flags = self.flags + if let flags = self.flags { + builder.flags = flags + } - builder.expireTimer = self.expireTimer + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } if let profileKey = self.profileKey { builder.profileKey = profileKey } - builder.timestamp = self.timestamp + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } if let quote = self.quote { builder.quote = quote.asProtobuf @@ -1676,6 +2552,30 @@ public enum SSKProtoError: Error { @objc public class SSKProtoNullMessage: NSObject { + // MARK: - SSKProtoNullMessageBuilder + + @objc public class SSKProtoNullMessageBuilder: NSObject { + + private var padding: Data? + + @objc public override init() {} + + @objc public func setPadding(_ value: Data) { + padding = value + } + + @objc public func build() throws -> SSKProtoNullMessage { + let proto = SignalServiceProtos_NullMessage.with { (builder) in + if let padding = self.padding { + builder.padding = padding + } + } + + let wrapper = try SSKProtoNullMessage.parseProto(proto) + return wrapper + } + } + @objc public let padding: Data? @objc public init(padding: Data?) { @@ -1742,6 +2642,38 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoReceiptMessageBuilder + + @objc public class SSKProtoReceiptMessageBuilder: NSObject { + + private var type: SSKProtoReceiptMessageType? + private var timestamp: [UInt64] + + @objc public override init() {} + + @objc public func setType(_ value: SSKProtoReceiptMessageType) { + type = value + } + + @objc public func addTimestamp(_ value: UInt64) { + timestamp.append(value) + } + + @objc public func build() throws -> SSKProtoReceiptMessage { + let proto = SignalServiceProtos_ReceiptMessage.with { (builder) in + if let type = self.type { + builder.type = SSKProtoReceiptMessageTypeUnwrap(type) + } + for item in timestamp { + builder.addTimestamp(item) + } + } + + let wrapper = try SSKProtoReceiptMessage.parseProto(proto) + return wrapper + } + } + @objc public let type: SSKProtoReceiptMessageType @objc public let timestamp: [UInt64] @@ -1762,10 +2694,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_ReceiptMessage) throws -> SSKProtoReceiptMessage { - var type: SSKProtoReceiptMessageType = .delivery - if proto.hasType { - type = SSKProtoReceiptMessageTypeWrap(proto.type) + guard proto.hasType else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: type") } + let type = SSKProtoReceiptMessageTypeWrap(proto.type) var timestamp: [UInt64] = [] for item in proto.timestamp { @@ -1829,6 +2761,54 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoVerifiedBuilder + + @objc public class SSKProtoVerifiedBuilder: NSObject { + + private var destination: String? + private var identityKey: Data? + private var state: SSKProtoVerifiedState? + private var nullMessage: Data? + + @objc public override init() {} + + @objc public func setDestination(_ value: String) { + destination = value + } + + @objc public func setIdentityKey(_ value: Data) { + identityKey = value + } + + @objc public func setState(_ value: SSKProtoVerifiedState) { + state = value + } + + @objc public func setNullMessage(_ value: Data) { + nullMessage = value + } + + @objc public func build() throws -> SSKProtoVerified { + let proto = SignalServiceProtos_Verified.with { (builder) in + if let destination = self.destination { + builder.destination = destination + } + if let identityKey = self.identityKey { + builder.identityKey = identityKey + } + if let state = self.state { + builder.state = SSKProtoVerifiedStateUnwrap(state) + } + if let nullMessage = self.nullMessage { + builder.nullMessage = nullMessage + } + } + + let wrapper = try SSKProtoVerified.parseProto(proto) + return wrapper + } + } + @objc public let destination: String? @objc public let identityKey: Data? @objc public let state: SSKProtoVerifiedState @@ -1855,10 +2835,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_Verified) throws -> SSKProtoVerified { - var destination: String? = nil - if proto.hasDestination { - destination = proto.destination + guard proto.hasDestination else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: destination") } + let destination = proto.destination var identityKey: Data? = nil if proto.hasIdentityKey { @@ -1911,15 +2891,63 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageSent: NSObject { + // MARK: - SSKProtoSyncMessageSentBuilder + + @objc public class SSKProtoSyncMessageSentBuilder: NSObject { + + private var destination: String? + private var timestamp: UInt64? + private var message: SSKProtoDataMessage? + private var expirationStartTimestamp: UInt64? + + @objc public override init() {} + + @objc public func setDestination(_ value: String) { + destination = value + } + + @objc public func setTimestamp(_ value: UInt64) { + timestamp = value + } + + @objc public func setMessage(_ value: SSKProtoDataMessage) { + message = value + } + + @objc public func setExpirationStartTimestamp(_ value: UInt64) { + expirationStartTimestamp = value + } + + @objc public func build() throws -> SSKProtoSyncMessageSent { + let proto = SignalServiceProtos_SyncMessage.Sent.with { (builder) in + if let destination = self.destination { + builder.destination = destination + } + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } + if let message = self.message { + builder.message = message.asProtobuf + } + if let expirationStartTimestamp = self.expirationStartTimestamp { + builder.expirationStartTimestamp = expirationStartTimestamp + } + } + + let wrapper = try SSKProtoSyncMessageSent.parseProto(proto) + return wrapper + } + } + @objc public let destination: String? - @objc public let timestamp: UInt64 + @objc public let timestamp: UInt64? @objc public let message: SSKProtoDataMessage? - @objc public let expirationStartTimestamp: UInt64 + @objc public let expirationStartTimestamp: UInt64? @objc public init(destination: String?, - timestamp: UInt64, + timestamp: UInt64?, message: SSKProtoDataMessage?, - expirationStartTimestamp: UInt64) { + expirationStartTimestamp: UInt64?) { self.destination = destination self.timestamp = timestamp self.message = message @@ -1942,7 +2970,7 @@ public enum SSKProtoError: Error { destination = proto.destination } - var timestamp: UInt64 = 0 + var timestamp: UInt64? = nil if proto.hasTimestamp { timestamp = proto.timestamp } @@ -1952,7 +2980,7 @@ public enum SSKProtoError: Error { message = try SSKProtoDataMessage.parseProto(proto.message) } - var expirationStartTimestamp: UInt64 = 0 + var expirationStartTimestamp: UInt64? = nil if proto.hasExpirationStartTimestamp { expirationStartTimestamp = proto.expirationStartTimestamp } @@ -1974,13 +3002,17 @@ public enum SSKProtoError: Error { builder.destination = destination } - builder.timestamp = self.timestamp + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } if let message = self.message { builder.message = message.asProtobuf } - builder.expirationStartTimestamp = self.expirationStartTimestamp + if let expirationStartTimestamp = self.expirationStartTimestamp { + builder.expirationStartTimestamp = expirationStartTimestamp + } } return proto @@ -1991,11 +3023,43 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageContacts: NSObject { + // MARK: - SSKProtoSyncMessageContactsBuilder + + @objc public class SSKProtoSyncMessageContactsBuilder: NSObject { + + private var blob: SSKProtoAttachmentPointer? + private var isComplete: Bool? + + @objc public override init() {} + + @objc public func setBlob(_ value: SSKProtoAttachmentPointer) { + blob = value + } + + @objc public func setIsComplete(_ value: Bool) { + isComplete = value + } + + @objc public func build() throws -> SSKProtoSyncMessageContacts { + let proto = SignalServiceProtos_SyncMessage.Contacts.with { (builder) in + if let blob = self.blob { + builder.blob = blob.asProtobuf + } + if let isComplete = self.isComplete { + builder.isComplete = isComplete + } + } + + let wrapper = try SSKProtoSyncMessageContacts.parseProto(proto) + return wrapper + } + } + @objc public let blob: SSKProtoAttachmentPointer? - @objc public let isComplete: Bool + @objc public let isComplete: Bool? @objc public init(blob: SSKProtoAttachmentPointer?, - isComplete: Bool) { + isComplete: Bool?) { self.blob = blob self.isComplete = isComplete } @@ -2011,12 +3075,12 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_SyncMessage.Contacts) throws -> SSKProtoSyncMessageContacts { - var blob: SSKProtoAttachmentPointer? = nil - if proto.hasBlob { - blob = try SSKProtoAttachmentPointer.parseProto(proto.blob) + guard proto.hasBlob else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: blob") } + let blob = try SSKProtoAttachmentPointer.parseProto(proto.blob) - var isComplete: Bool = false + var isComplete: Bool? = false if proto.hasIsComplete { isComplete = proto.isComplete } @@ -2040,7 +3104,9 @@ public enum SSKProtoError: Error { builder.blob = blob.asProtobuf } - builder.isComplete = self.isComplete + if let isComplete = self.isComplete { + builder.isComplete = isComplete + } } return proto @@ -2051,6 +3117,30 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageGroups: NSObject { + // MARK: - SSKProtoSyncMessageGroupsBuilder + + @objc public class SSKProtoSyncMessageGroupsBuilder: NSObject { + + private var blob: SSKProtoAttachmentPointer? + + @objc public override init() {} + + @objc public func setBlob(_ value: SSKProtoAttachmentPointer) { + blob = value + } + + @objc public func build() throws -> SSKProtoSyncMessageGroups { + let proto = SignalServiceProtos_SyncMessage.Groups.with { (builder) in + if let blob = self.blob { + builder.blob = blob.asProtobuf + } + } + + let wrapper = try SSKProtoSyncMessageGroups.parseProto(proto) + return wrapper + } + } + @objc public let blob: SSKProtoAttachmentPointer? @objc public init(blob: SSKProtoAttachmentPointer?) { @@ -2100,6 +3190,30 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageBlocked: NSObject { + // MARK: - SSKProtoSyncMessageBlockedBuilder + + @objc public class SSKProtoSyncMessageBlockedBuilder: NSObject { + + private var numbers: [String] + + @objc public override init() {} + + @objc public func addNumbers(_ value: String) { + numbers.append(value) + } + + @objc public func build() throws -> SSKProtoSyncMessageBlocked { + let proto = SignalServiceProtos_SyncMessage.Blocked.with { (builder) in + for item in numbers { + builder.addNumbers(item) + } + } + + let wrapper = try SSKProtoSyncMessageBlocked.parseProto(proto) + return wrapper + } + } + @objc public let numbers: [String] @objc public init(numbers: [String]) { @@ -2178,6 +3292,30 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoSyncMessageRequestBuilder + + @objc public class SSKProtoSyncMessageRequestBuilder: NSObject { + + private var type: SSKProtoSyncMessageRequestType? + + @objc public override init() {} + + @objc public func setType(_ value: SSKProtoSyncMessageRequestType) { + type = value + } + + @objc public func build() throws -> SSKProtoSyncMessageRequest { + let proto = SignalServiceProtos_SyncMessage.Request.with { (builder) in + if let type = self.type { + builder.type = SSKProtoSyncMessageRequestTypeUnwrap(type) + } + } + + let wrapper = try SSKProtoSyncMessageRequest.parseProto(proto) + return wrapper + } + } + @objc public let type: SSKProtoSyncMessageRequestType @objc public init(type: SSKProtoSyncMessageRequestType) { @@ -2195,10 +3333,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_SyncMessage.Request) throws -> SSKProtoSyncMessageRequest { - var type: SSKProtoSyncMessageRequestType = .unknown - if proto.hasType { - type = SSKProtoSyncMessageRequestTypeWrap(proto.type) + guard proto.hasType else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: type") } + let type = SSKProtoSyncMessageRequestTypeWrap(proto.type) // MARK: - Begin Validation Logic for SSKProtoSyncMessageRequest - @@ -2225,6 +3363,38 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageRead: NSObject { + // MARK: - SSKProtoSyncMessageReadBuilder + + @objc public class SSKProtoSyncMessageReadBuilder: NSObject { + + private var sender: String? + private var timestamp: UInt64? + + @objc public override init() {} + + @objc public func setSender(_ value: String) { + sender = value + } + + @objc public func setTimestamp(_ value: UInt64) { + timestamp = value + } + + @objc public func build() throws -> SSKProtoSyncMessageRead { + let proto = SignalServiceProtos_SyncMessage.Read.with { (builder) in + if let sender = self.sender { + builder.sender = sender + } + if let timestamp = self.timestamp { + builder.timestamp = timestamp + } + } + + let wrapper = try SSKProtoSyncMessageRead.parseProto(proto) + return wrapper + } + } + @objc public let sender: String? @objc public let timestamp: UInt64 @@ -2245,15 +3415,15 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_SyncMessage.Read) throws -> SSKProtoSyncMessageRead { - var sender: String? = nil - if proto.hasSender { - sender = proto.sender + guard proto.hasSender else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: sender") } + let sender = proto.sender - var timestamp: UInt64 = 0 - if proto.hasTimestamp { - timestamp = proto.timestamp + guard proto.hasTimestamp else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: timestamp") } + let timestamp = proto.timestamp // MARK: - Begin Validation Logic for SSKProtoSyncMessageRead - @@ -2288,9 +3458,33 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessageConfiguration: NSObject { - @objc public let readReceipts: Bool + // MARK: - SSKProtoSyncMessageConfigurationBuilder - @objc public init(readReceipts: Bool) { + @objc public class SSKProtoSyncMessageConfigurationBuilder: NSObject { + + private var readReceipts: Bool? + + @objc public override init() {} + + @objc public func setReadReceipts(_ value: Bool) { + readReceipts = value + } + + @objc public func build() throws -> SSKProtoSyncMessageConfiguration { + let proto = SignalServiceProtos_SyncMessage.Configuration.with { (builder) in + if let readReceipts = self.readReceipts { + builder.readReceipts = readReceipts + } + } + + let wrapper = try SSKProtoSyncMessageConfiguration.parseProto(proto) + return wrapper + } + } + + @objc public let readReceipts: Bool? + + @objc public init(readReceipts: Bool?) { self.readReceipts = readReceipts } @@ -2305,7 +3499,7 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_SyncMessage.Configuration) throws -> SSKProtoSyncMessageConfiguration { - var readReceipts: Bool = false + var readReceipts: Bool? = nil if proto.hasReadReceipts { readReceipts = proto.readReceipts } @@ -2320,7 +3514,9 @@ public enum SSKProtoError: Error { fileprivate var asProtobuf: SignalServiceProtos_SyncMessage.Configuration { let proto = SignalServiceProtos_SyncMessage.Configuration.with { (builder) in - builder.readReceipts = self.readReceipts + if let readReceipts = self.readReceipts { + builder.readReceipts = readReceipts + } } return proto @@ -2331,6 +3527,94 @@ public enum SSKProtoError: Error { @objc public class SSKProtoSyncMessage: NSObject { + // MARK: - SSKProtoSyncMessageBuilder + + @objc public class SSKProtoSyncMessageBuilder: NSObject { + + private var sent: SSKProtoSyncMessageSent? + private var contacts: SSKProtoSyncMessageContacts? + private var groups: SSKProtoSyncMessageGroups? + private var request: SSKProtoSyncMessageRequest? + private var read: [SSKProtoSyncMessageRead] + private var blocked: SSKProtoSyncMessageBlocked? + private var verified: SSKProtoVerified? + private var configuration: SSKProtoSyncMessageConfiguration? + private var padding: Data? + + @objc public override init() {} + + @objc public func setSent(_ value: SSKProtoSyncMessageSent) { + sent = value + } + + @objc public func setContacts(_ value: SSKProtoSyncMessageContacts) { + contacts = value + } + + @objc public func setGroups(_ value: SSKProtoSyncMessageGroups) { + groups = value + } + + @objc public func setRequest(_ value: SSKProtoSyncMessageRequest) { + request = value + } + + @objc public func addRead(_ value: SSKProtoSyncMessageRead) { + read.append(value) + } + + @objc public func setBlocked(_ value: SSKProtoSyncMessageBlocked) { + blocked = value + } + + @objc public func setVerified(_ value: SSKProtoVerified) { + verified = value + } + + @objc public func setConfiguration(_ value: SSKProtoSyncMessageConfiguration) { + configuration = value + } + + @objc public func setPadding(_ value: Data) { + padding = value + } + + @objc public func build() throws -> SSKProtoSyncMessage { + let proto = SignalServiceProtos_SyncMessage.with { (builder) in + if let sent = self.sent { + builder.sent = sent.asProtobuf + } + if let contacts = self.contacts { + builder.contacts = contacts.asProtobuf + } + if let groups = self.groups { + builder.groups = groups.asProtobuf + } + if let request = self.request { + builder.request = request.asProtobuf + } + for item in read { + builder.addRead(item.asProtobuf) + } + if let blocked = self.blocked { + builder.blocked = blocked.asProtobuf + } + if let verified = self.verified { + builder.verified = verified.asProtobuf + } + if let configuration = self.configuration { + builder.configuration = configuration.asProtobuf + } + if let padding = self.padding { + builder.padding = padding + } + } + + let wrapper = try SSKProtoSyncMessage.parseProto(proto) + return wrapper + } + } + @objc public let sent: SSKProtoSyncMessageSent? @objc public let contacts: SSKProtoSyncMessageContacts? @objc public let groups: SSKProtoSyncMessageGroups? @@ -2501,27 +3785,123 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoAttachmentPointerBuilder + + @objc public class SSKProtoAttachmentPointerBuilder: NSObject { + + private var id: UInt64? + private var contentType: String? + private var key: Data? + private var size: UInt32? + private var thumbnail: Data? + private var digest: Data? + private var fileName: String? + private var flags: UInt32? + private var width: UInt32? + private var height: UInt32? + + @objc public override init() {} + + @objc public func setId(_ value: UInt64) { + id = value + } + + @objc public func setContentType(_ value: String) { + contentType = value + } + + @objc public func setKey(_ value: Data) { + key = value + } + + @objc public func setSize(_ value: UInt32) { + size = value + } + + @objc public func setThumbnail(_ value: Data) { + thumbnail = value + } + + @objc public func setDigest(_ value: Data) { + digest = value + } + + @objc public func setFileName(_ value: String) { + fileName = value + } + + @objc public func setFlags(_ value: UInt32) { + flags = value + } + + @objc public func setWidth(_ value: UInt32) { + width = value + } + + @objc public func setHeight(_ value: UInt32) { + height = value + } + + @objc public func build() throws -> SSKProtoAttachmentPointer { + let proto = SignalServiceProtos_AttachmentPointer.with { (builder) in + if let id = self.id { + builder.id = id + } + if let contentType = self.contentType { + builder.contentType = contentType + } + if let key = self.key { + builder.key = key + } + if let size = self.size { + builder.size = size + } + if let thumbnail = self.thumbnail { + builder.thumbnail = thumbnail + } + if let digest = self.digest { + builder.digest = digest + } + if let fileName = self.fileName { + builder.fileName = fileName + } + if let flags = self.flags { + builder.flags = flags + } + if let width = self.width { + builder.width = width + } + if let height = self.height { + builder.height = height + } + } + + let wrapper = try SSKProtoAttachmentPointer.parseProto(proto) + return wrapper + } + } + @objc public let id: UInt64 @objc public let contentType: String? @objc public let key: Data? - @objc public let size: UInt32 + @objc public let size: UInt32? @objc public let thumbnail: Data? @objc public let digest: Data? @objc public let fileName: String? - @objc public let flags: UInt32 - @objc public let width: UInt32 - @objc public let height: UInt32 + @objc public let flags: UInt32? + @objc public let width: UInt32? + @objc public let height: UInt32? @objc public init(id: UInt64, contentType: String?, key: Data?, - size: UInt32, + size: UInt32?, thumbnail: Data?, digest: Data?, fileName: String?, - flags: UInt32, - width: UInt32, - height: UInt32) { + flags: UInt32?, + width: UInt32?, + height: UInt32?) { self.id = id self.contentType = contentType self.key = key @@ -2545,10 +3925,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_AttachmentPointer) throws -> SSKProtoAttachmentPointer { - var id: UInt64 = 0 - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id var contentType: String? = nil if proto.hasContentType { @@ -2560,7 +3940,7 @@ public enum SSKProtoError: Error { key = proto.key } - var size: UInt32 = 0 + var size: UInt32? = nil if proto.hasSize { size = proto.size } @@ -2580,17 +3960,17 @@ public enum SSKProtoError: Error { fileName = proto.fileName } - var flags: UInt32 = 0 + var flags: UInt32? = nil if proto.hasFlags { flags = proto.flags } - var width: UInt32 = 0 + var width: UInt32? = nil if proto.hasWidth { width = proto.width } - var height: UInt32 = 0 + var height: UInt32? = nil if proto.hasHeight { height = proto.height } @@ -2628,7 +4008,9 @@ public enum SSKProtoError: Error { builder.key = key } - builder.size = self.size + if let size = self.size { + builder.size = size + } if let thumbnail = self.thumbnail { builder.thumbnail = thumbnail @@ -2642,11 +4024,17 @@ public enum SSKProtoError: Error { builder.fileName = fileName } - builder.flags = self.flags + if let flags = self.flags { + builder.flags = flags + } - builder.width = self.width + if let width = self.width { + builder.width = width + } - builder.height = self.height + if let height = self.height { + builder.height = height + } } return proto @@ -2687,6 +4075,62 @@ public enum SSKProtoError: Error { } } + // MARK: - SSKProtoGroupContextBuilder + + @objc public class SSKProtoGroupContextBuilder: NSObject { + + private var id: Data? + private var type: SSKProtoGroupContextType? + private var name: String? + private var members: [String] + private var avatar: SSKProtoAttachmentPointer? + + @objc public override init() {} + + @objc public func setId(_ value: Data) { + id = value + } + + @objc public func setType(_ value: SSKProtoGroupContextType) { + type = value + } + + @objc public func setName(_ value: String) { + name = value + } + + @objc public func addMembers(_ value: String) { + members.append(value) + } + + @objc public func setAvatar(_ value: SSKProtoAttachmentPointer) { + avatar = value + } + + @objc public func build() throws -> SSKProtoGroupContext { + let proto = SignalServiceProtos_GroupContext.with { (builder) in + if let id = self.id { + builder.id = id + } + if let type = self.type { + builder.type = SSKProtoGroupContextTypeUnwrap(type) + } + if let name = self.name { + builder.name = name + } + for item in members { + builder.addMembers(item) + } + if let avatar = self.avatar { + builder.avatar = avatar.asProtobuf + } + } + + let wrapper = try SSKProtoGroupContext.parseProto(proto) + return wrapper + } + } + @objc public let id: Data? @objc public let type: SSKProtoGroupContextType @objc public let name: String? @@ -2716,15 +4160,15 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_GroupContext) throws -> SSKProtoGroupContext { - var id: Data? = nil - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id - var type: SSKProtoGroupContextType = .unknown - if proto.hasType { - type = SSKProtoGroupContextTypeWrap(proto.type) + guard proto.hasType else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: type") } + let type = SSKProtoGroupContextTypeWrap(proto.type) var name: String? = nil if proto.hasName { @@ -2792,11 +4236,43 @@ public enum SSKProtoError: Error { @objc public class SSKProtoContactDetailsAvatar: NSObject { + // MARK: - SSKProtoContactDetailsAvatarBuilder + + @objc public class SSKProtoContactDetailsAvatarBuilder: NSObject { + + private var contentType: String? + private var length: UInt32? + + @objc public override init() {} + + @objc public func setContentType(_ value: String) { + contentType = value + } + + @objc public func setLength(_ value: UInt32) { + length = value + } + + @objc public func build() throws -> SSKProtoContactDetailsAvatar { + let proto = SignalServiceProtos_ContactDetails.Avatar.with { (builder) in + if let contentType = self.contentType { + builder.contentType = contentType + } + if let length = self.length { + builder.length = length + } + } + + let wrapper = try SSKProtoContactDetailsAvatar.parseProto(proto) + return wrapper + } + } + @objc public let contentType: String? - @objc public let length: UInt32 + @objc public let length: UInt32? @objc public init(contentType: String?, - length: UInt32) { + length: UInt32?) { self.contentType = contentType self.length = length } @@ -2817,7 +4293,7 @@ public enum SSKProtoError: Error { contentType = proto.contentType } - var length: UInt32 = 0 + var length: UInt32? = nil if proto.hasLength { length = proto.length } @@ -2837,7 +4313,9 @@ public enum SSKProtoError: Error { builder.contentType = contentType } - builder.length = self.length + if let length = self.length { + builder.length = length + } } return proto @@ -2848,14 +4326,94 @@ public enum SSKProtoError: Error { @objc public class SSKProtoContactDetails: NSObject { + // MARK: - SSKProtoContactDetailsBuilder + + @objc public class SSKProtoContactDetailsBuilder: NSObject { + + private var number: String? + private var name: String? + private var avatar: SSKProtoContactDetailsAvatar? + private var color: String? + private var verified: SSKProtoVerified? + private var profileKey: Data? + private var blocked: Bool? + private var expireTimer: UInt32? + + @objc public override init() {} + + @objc public func setNumber(_ value: String) { + number = value + } + + @objc public func setName(_ value: String) { + name = value + } + + @objc public func setAvatar(_ value: SSKProtoContactDetailsAvatar) { + avatar = value + } + + @objc public func setColor(_ value: String) { + color = value + } + + @objc public func setVerified(_ value: SSKProtoVerified) { + verified = value + } + + @objc public func setProfileKey(_ value: Data) { + profileKey = value + } + + @objc public func setBlocked(_ value: Bool) { + blocked = value + } + + @objc public func setExpireTimer(_ value: UInt32) { + expireTimer = value + } + + @objc public func build() throws -> SSKProtoContactDetails { + let proto = SignalServiceProtos_ContactDetails.with { (builder) in + if let number = self.number { + builder.number = number + } + if let name = self.name { + builder.name = name + } + if let avatar = self.avatar { + builder.avatar = avatar.asProtobuf + } + if let color = self.color { + builder.color = color + } + if let verified = self.verified { + builder.verified = verified.asProtobuf + } + if let profileKey = self.profileKey { + builder.profileKey = profileKey + } + if let blocked = self.blocked { + builder.blocked = blocked + } + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } + } + + let wrapper = try SSKProtoContactDetails.parseProto(proto) + return wrapper + } + } + @objc public let number: String? @objc public let name: String? @objc public let avatar: SSKProtoContactDetailsAvatar? @objc public let color: String? @objc public let verified: SSKProtoVerified? @objc public let profileKey: Data? - @objc public let blocked: Bool - @objc public let expireTimer: UInt32 + @objc public let blocked: Bool? + @objc public let expireTimer: UInt32? @objc public init(number: String?, name: String?, @@ -2863,8 +4421,8 @@ public enum SSKProtoError: Error { color: String?, verified: SSKProtoVerified?, profileKey: Data?, - blocked: Bool, - expireTimer: UInt32) { + blocked: Bool?, + expireTimer: UInt32?) { self.number = number self.name = name self.avatar = avatar @@ -2886,10 +4444,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_ContactDetails) throws -> SSKProtoContactDetails { - var number: String? = nil - if proto.hasNumber { - number = proto.number + guard proto.hasNumber else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: number") } + let number = proto.number var name: String? = nil if proto.hasName { @@ -2916,12 +4474,12 @@ public enum SSKProtoError: Error { profileKey = proto.profileKey } - var blocked: Bool = false + var blocked: Bool? = nil if proto.hasBlocked { blocked = proto.blocked } - var expireTimer: UInt32 = 0 + var expireTimer: UInt32? = nil if proto.hasExpireTimer { expireTimer = proto.expireTimer } @@ -2971,9 +4529,13 @@ public enum SSKProtoError: Error { builder.profileKey = profileKey } - builder.blocked = self.blocked + if let blocked = self.blocked { + builder.blocked = blocked + } - builder.expireTimer = self.expireTimer + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } } return proto @@ -2984,11 +4546,43 @@ public enum SSKProtoError: Error { @objc public class SSKProtoGroupDetailsAvatar: NSObject { + // MARK: - SSKProtoGroupDetailsAvatarBuilder + + @objc public class SSKProtoGroupDetailsAvatarBuilder: NSObject { + + private var contentType: String? + private var length: UInt32? + + @objc public override init() {} + + @objc public func setContentType(_ value: String) { + contentType = value + } + + @objc public func setLength(_ value: UInt32) { + length = value + } + + @objc public func build() throws -> SSKProtoGroupDetailsAvatar { + let proto = SignalServiceProtos_GroupDetails.Avatar.with { (builder) in + if let contentType = self.contentType { + builder.contentType = contentType + } + if let length = self.length { + builder.length = length + } + } + + let wrapper = try SSKProtoGroupDetailsAvatar.parseProto(proto) + return wrapper + } + } + @objc public let contentType: String? - @objc public let length: UInt32 + @objc public let length: UInt32? @objc public init(contentType: String?, - length: UInt32) { + length: UInt32?) { self.contentType = contentType self.length = length } @@ -3009,7 +4603,7 @@ public enum SSKProtoError: Error { contentType = proto.contentType } - var length: UInt32 = 0 + var length: UInt32? = nil if proto.hasLength { length = proto.length } @@ -3029,7 +4623,9 @@ public enum SSKProtoError: Error { builder.contentType = contentType } - builder.length = self.length + if let length = self.length { + builder.length = length + } } return proto @@ -3040,20 +4636,92 @@ public enum SSKProtoError: Error { @objc public class SSKProtoGroupDetails: NSObject { + // MARK: - SSKProtoGroupDetailsBuilder + + @objc public class SSKProtoGroupDetailsBuilder: NSObject { + + private var id: Data? + private var name: String? + private var members: [String] + private var avatar: SSKProtoGroupDetailsAvatar? + private var active: Bool? + private var expireTimer: UInt32? + private var color: String? + + @objc public override init() {} + + @objc public func setId(_ value: Data) { + id = value + } + + @objc public func setName(_ value: String) { + name = value + } + + @objc public func addMembers(_ value: String) { + members.append(value) + } + + @objc public func setAvatar(_ value: SSKProtoGroupDetailsAvatar) { + avatar = value + } + + @objc public func setActive(_ value: Bool) { + active = value + } + + @objc public func setExpireTimer(_ value: UInt32) { + expireTimer = value + } + + @objc public func setColor(_ value: String) { + color = value + } + + @objc public func build() throws -> SSKProtoGroupDetails { + let proto = SignalServiceProtos_GroupDetails.with { (builder) in + if let id = self.id { + builder.id = id + } + if let name = self.name { + builder.name = name + } + for item in members { + builder.addMembers(item) + } + if let avatar = self.avatar { + builder.avatar = avatar.asProtobuf + } + if let active = self.active { + builder.active = active + } + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } + if let color = self.color { + builder.color = color + } + } + + let wrapper = try SSKProtoGroupDetails.parseProto(proto) + return wrapper + } + } + @objc public let id: Data? @objc public let name: String? @objc public let members: [String] @objc public let avatar: SSKProtoGroupDetailsAvatar? - @objc public let active: Bool - @objc public let expireTimer: UInt32 + @objc public let active: Bool? + @objc public let expireTimer: UInt32? @objc public let color: String? @objc public init(id: Data?, name: String?, members: [String], avatar: SSKProtoGroupDetailsAvatar?, - active: Bool, - expireTimer: UInt32, + active: Bool?, + expireTimer: UInt32?, color: String?) { self.id = id self.name = name @@ -3075,10 +4743,10 @@ public enum SSKProtoError: Error { } fileprivate class func parseProto(_ proto: SignalServiceProtos_GroupDetails) throws -> SSKProtoGroupDetails { - var id: Data? = nil - if proto.hasID { - id = proto.id + guard proto.hasID else { + throw SSKProtoError.invalidProtobuf(description: "\(logTag) missing required field: id") } + let id = proto.id var name: String? = nil if proto.hasName { @@ -3096,12 +4764,12 @@ public enum SSKProtoError: Error { avatar = try SSKProtoGroupDetailsAvatar.parseProto(proto.avatar) } - var active: Bool = true + var active: Bool? = true if proto.hasActive { active = proto.active } - var expireTimer: UInt32 = 0 + var expireTimer: UInt32? = nil if proto.hasExpireTimer { expireTimer = proto.expireTimer } @@ -3149,9 +4817,13 @@ public enum SSKProtoError: Error { builder.avatar = avatar.asProtobuf } - builder.active = self.active + if let active = self.active { + builder.active = active + } - builder.expireTimer = self.expireTimer + if let expireTimer = self.expireTimer { + builder.expireTimer = expireTimer + } if let color = self.color { builder.color = color diff --git a/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift b/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift index d0e63089a..86f30894a 100644 --- a/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift +++ b/SignalServiceKit/src/Protos/Generated/SignalService.pb.swift @@ -32,6 +32,7 @@ struct SignalServiceProtos_Envelope { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var type: SignalServiceProtos_Envelope.TypeEnum { get {return _type ?? .unknown} set {_type = newValue} @@ -41,6 +42,7 @@ struct SignalServiceProtos_Envelope { /// Clears the value of `type`. Subsequent reads from it will return its default value. mutating func clearType() {self._type = nil} + /// @required var source: String { get {return _source ?? String()} set {_source = newValue} @@ -50,6 +52,7 @@ struct SignalServiceProtos_Envelope { /// Clears the value of `source`. Subsequent reads from it will return its default value. mutating func clearSource() {self._source = nil} + /// @required var sourceDevice: UInt32 { get {return _sourceDevice ?? 0} set {_sourceDevice = newValue} @@ -68,6 +71,7 @@ struct SignalServiceProtos_Envelope { /// Clears the value of `relay`. Subsequent reads from it will return its default value. mutating func clearRelay() {self._relay = nil} + /// @required var timestamp: UInt64 { get {return _timestamp ?? 0} set {_timestamp = newValue} @@ -266,6 +270,7 @@ struct SignalServiceProtos_CallMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -299,6 +304,7 @@ struct SignalServiceProtos_CallMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -332,6 +338,7 @@ struct SignalServiceProtos_CallMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -383,6 +390,7 @@ struct SignalServiceProtos_CallMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -404,6 +412,7 @@ struct SignalServiceProtos_CallMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -539,6 +548,7 @@ struct SignalServiceProtos_DataMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -548,6 +558,7 @@ struct SignalServiceProtos_DataMessage { /// Clears the value of `id`. Subsequent reads from it will return its default value. mutating func clearID() {self._id = nil} + /// @required var author: String { get {return _author ?? String()} set {_author = newValue} @@ -773,6 +784,7 @@ struct SignalServiceProtos_DataMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var value: String { get {return _value ?? String()} set {_value = newValue} @@ -846,6 +858,7 @@ struct SignalServiceProtos_DataMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var value: String { get {return _value ?? String()} set {_value = newValue} @@ -1110,6 +1123,7 @@ struct SignalServiceProtos_ReceiptMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var type: SignalServiceProtos_ReceiptMessage.TypeEnum { get {return _type ?? .delivery} set {_type = newValue} @@ -1159,6 +1173,7 @@ struct SignalServiceProtos_Verified { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var destination: String { get {return _destination ?? String()} set {_destination = newValue} @@ -1371,6 +1386,7 @@ struct SignalServiceProtos_SyncMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var blob: SignalServiceProtos_AttachmentPointer { get {return _storage._blob ?? SignalServiceProtos_AttachmentPointer()} set {_uniqueStorage()._blob = newValue} @@ -1435,6 +1451,7 @@ struct SignalServiceProtos_SyncMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var type: SignalServiceProtos_SyncMessage.Request.TypeEnum { get {return _type ?? .unknown} set {_type = newValue} @@ -1491,6 +1508,7 @@ struct SignalServiceProtos_SyncMessage { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var sender: String { get {return _sender ?? String()} set {_sender = newValue} @@ -1500,6 +1518,7 @@ struct SignalServiceProtos_SyncMessage { /// Clears the value of `sender`. Subsequent reads from it will return its default value. mutating func clearSender() {self._sender = nil} + /// @required var timestamp: UInt64 { get {return _timestamp ?? 0} set {_timestamp = newValue} @@ -1548,6 +1567,7 @@ struct SignalServiceProtos_AttachmentPointer { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: UInt64 { get {return _id ?? 0} set {_id = newValue} @@ -1682,6 +1702,7 @@ struct SignalServiceProtos_GroupContext { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: Data { get {return _storage._id ?? SwiftProtobuf.Internal.emptyData} set {_uniqueStorage()._id = newValue} @@ -1691,6 +1712,7 @@ struct SignalServiceProtos_GroupContext { /// Clears the value of `id`. Subsequent reads from it will return its default value. mutating func clearID() {_storage._id = nil} + /// @required var type: SignalServiceProtos_GroupContext.TypeEnum { get {return _storage._type ?? .unknown} set {_uniqueStorage()._type = newValue} @@ -1770,6 +1792,7 @@ struct SignalServiceProtos_ContactDetails { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var number: String { get {return _storage._number ?? String()} set {_uniqueStorage()._number = newValue} @@ -1885,6 +1908,7 @@ struct SignalServiceProtos_GroupDetails { // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + /// @required var id: Data { get {return _storage._id ?? SwiftProtobuf.Internal.emptyData} set {_uniqueStorage()._id = newValue}