Skip to content

Commit

Permalink
Add isIntialized to Messages.
Browse files Browse the repository at this point in the history
- Add isInitialized Message protocol
- Provide default isInitialized so the generator can emit a custom one as needed.
- Add isInitialized to ExtensionFields so Message can call to it.
- Add Internal.swift as a place to hold public code (because the generated code
  has to be able to call it), but that is not intended to be part of the
  "developer public" api.
  - Helpers for checking a map and repeated field for being initialized.
- Generate isInitialized - Walk the message fields to decided if
  directly/indirectly can have messages with required fields.

Re apple#98
  • Loading branch information
thomasvl committed Feb 14, 2017
1 parent 27c727f commit fa9de15
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Sources/SwiftProtobuf/ExtensionFieldValueSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,13 @@ public struct ExtensionFieldValueSet: Equatable, Sequence {
}
return nil
}

public var isInitialized: Bool {
for (_, v) in values {
if !v.isInitialized {
return false
}
}
return true
}
}
31 changes: 31 additions & 0 deletions Sources/SwiftProtobuf/ExtensionFields.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ public protocol AnyExtensionField: CustomDebugStringConvertible {

/// Fields know their own type, so can dispatch to a visitor
func traverse(visitor: Visitor) throws

/// Check if the field is initialized.
var isInitialized: Bool { get }
}

public extension AnyExtensionField {
// Default implementation for extensions fields. The message types below provide
// custom versions.
var isInitialized: Bool { return true }
}

///
Expand Down Expand Up @@ -247,6 +256,13 @@ public struct OptionalMessageExtensionField<M: Message & Equatable>:
value: v, fieldNumber: protobufExtension.protoFieldNumber)
}
}

public var isInitialized: Bool {
if let v = value {
return v.isInitialized
}
return true
}
}

public struct RepeatedMessageExtensionField<M: Message & Equatable>:
Expand Down Expand Up @@ -294,6 +310,10 @@ public struct RepeatedMessageExtensionField<M: Message & Equatable>:
value: value, fieldNumber: protobufExtension.protoFieldNumber)
}
}

public var isInitialized: Bool {
return Internal.areAllInitialized(value)
}
}

//
Expand Down Expand Up @@ -337,6 +357,13 @@ public struct OptionalGroupExtensionField<G: Message & Hashable>:
value: v, fieldNumber: protobufExtension.protoFieldNumber)
}
}

public var isInitialized: Bool {
if let v = value {
return v.isInitialized
}
return true
}
}

public struct RepeatedGroupExtensionField<G: Message & Hashable>:
Expand Down Expand Up @@ -384,4 +411,8 @@ public struct RepeatedGroupExtensionField<G: Message & Hashable>:
value: value, fieldNumber: protobufExtension.protoFieldNumber)
}
}

public var isInitialized: Bool {
return Internal.areAllInitialized(value)
}
}
42 changes: 42 additions & 0 deletions Sources/SwiftProtobuf/Internal.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Sources/SwiftProtobuf/Message.swift - Message support
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Internal helpers on Messages for the library. These are public
/// just so the generated code can call them, but shouldn't be called
/// by developers directly.
///
// -----------------------------------------------------------------------------


import Foundation
import Swift

public struct Internal {
private init() {}

public static func areAllInitialized(_ listOfMessages: [Message]) -> Bool {
for msg in listOfMessages {
if !msg.isInitialized {
return false
}
}
return true
}

public static func areAllInitialized<K: Hashable>(_ mapToMessages: [K: Message]) -> Bool {
for (_, msg) in mapToMessages {
if !msg.isInitialized {
return false
}
}
return true
}

}
10 changes: 10 additions & 0 deletions Sources/SwiftProtobuf/Message.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public protocol Message: CustomDebugStringConvertible {
var anyTypePrefix: String { get }
var anyTypeURL: String { get }

/// Check if all required fields (if any) have values set on this message
/// on any messages withing this message.
var isInitialized: Bool { get }

//
// General serialization/deserialization machinery
//
Expand Down Expand Up @@ -116,6 +120,12 @@ public protocol Message: CustomDebugStringConvertible {
}

public extension Message {

var isInitialized: Bool {
// The generated code will include a specialization as needed.
return true;
}

var hashValue: Int {
let visitor = HashVisitor()
try? traverse(visitor: visitor)
Expand Down
24 changes: 24 additions & 0 deletions Sources/protoc-gen-swift/MessageFieldGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,30 @@ struct MessageFieldGenerator {
(descriptor.options.hasPacked ? descriptor.options.packed : isProto3)}
var isRepeated: Bool {return descriptor.isRepeated}

// True/False if the field will be hold a Message. If the field is a map,
// the value type for the map is checked.
var fieldHoldsMessage: Bool {
switch descriptor.label {
case .required, .optional:
let type = descriptor.type
return type == .message || type == .group
case .repeated:
let type = descriptor.type
if type == .group { return true }
if type == .message {
let m = context.getMessageForPath(path: descriptor.typeName)!
if m.options.mapEntry {
let valueField = m.field[1]
return valueField.type == .message
} else {
return true
}
} else {
return false
}
}
}

var name: String {return descriptor.name}

var swiftBaseType: String {return descriptor.getSwiftBaseType(context: context)}
Expand Down
Loading

0 comments on commit fa9de15

Please sign in to comment.