Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use heap-based storage only when a Protobuf has a singular transitive recursion #900

Merged
merged 10 commits into from
Oct 11, 2019
Prev Previous commit
Next Next commit
Commit regenerated protobufs per instructions in the Makefile:
- `make regenerate` to rebuild the protos used by the runtime and plugin
- `make test-runtime` to verify that the runtime works correctly with the new changes
- `make reference` to update the Reference directory
- MANUALLY go through `git diff Reference` to verify that the generated Swift changed in the way you expect
- `make clean build test` to do a final check

Test results:

CONFORMANCE SUITE PASSED: 1940 successes, 0 skipped, 0 expected failures, 0 unexpected failures.
CONFORMANCE SUITE PASSED: 63 successes, 0 skipped, 0 expected failures, 0 unexpected failures.

Fixes #735 and #733.
ydnar committed Sep 27, 2019
commit 9c685ea0fee1d3ea265830fa2429199102bdcc68
221 changes: 82 additions & 139 deletions Reference/conformance/conformance.pb.swift
Original file line number Diff line number Diff line change
@@ -206,82 +206,67 @@ struct Conformance_ConformanceRequest {
/// TODO(haberman): if/when we expand the conformance tests to support proto2,
/// we will want to include a field that lets the payload/response be a
/// protobuf_test_messages.proto2.TestAllTypes message instead.
var payload: OneOf_Payload? {
get {return _storage._payload}
set {_uniqueStorage()._payload = newValue}
}
var payload: Conformance_ConformanceRequest.OneOf_Payload? = nil

var protobufPayload: Data {
get {
if case .protobufPayload(let v)? = _storage._payload {return v}
if case .protobufPayload(let v)? = payload {return v}
return SwiftProtobuf.Internal.emptyData
}
set {_uniqueStorage()._payload = .protobufPayload(newValue)}
set {payload = .protobufPayload(newValue)}
}

var jsonPayload: String {
get {
if case .jsonPayload(let v)? = _storage._payload {return v}
if case .jsonPayload(let v)? = payload {return v}
return String()
}
set {_uniqueStorage()._payload = .jsonPayload(newValue)}
set {payload = .jsonPayload(newValue)}
}

/// Google internal only. Opensource testees just skip it.
var jspbPayload: String {
get {
if case .jspbPayload(let v)? = _storage._payload {return v}
if case .jspbPayload(let v)? = payload {return v}
return String()
}
set {_uniqueStorage()._payload = .jspbPayload(newValue)}
set {payload = .jspbPayload(newValue)}
}

var textPayload: String {
get {
if case .textPayload(let v)? = _storage._payload {return v}
if case .textPayload(let v)? = payload {return v}
return String()
}
set {_uniqueStorage()._payload = .textPayload(newValue)}
set {payload = .textPayload(newValue)}
}

/// Which format should the testee serialize its message to?
var requestedOutputFormat: Conformance_WireFormat {
get {return _storage._requestedOutputFormat}
set {_uniqueStorage()._requestedOutputFormat = newValue}
}
var requestedOutputFormat: Conformance_WireFormat = .unspecified

/// The full name for the test message to use; for the moment, either:
/// protobuf_test_messages.proto3.TestAllTypesProto3 or
/// protobuf_test_messages.proto2.TestAllTypesProto2.
var messageType: String {
get {return _storage._messageType}
set {_uniqueStorage()._messageType = newValue}
}
var messageType: String = String()

/// Each test is given a specific test category. Some category may need
/// spedific support in testee programs. Refer to the defintion of TestCategory
/// for more information.
var testCategory: Conformance_TestCategory {
get {return _storage._testCategory}
set {_uniqueStorage()._testCategory = newValue}
}
var testCategory: Conformance_TestCategory = .unspecifiedTest

/// Specify details for how to encode jspb.
var jspbEncodingOptions: Conformance_JspbEncodingConfig {
get {return _storage._jspbEncodingOptions ?? Conformance_JspbEncodingConfig()}
set {_uniqueStorage()._jspbEncodingOptions = newValue}
get {return _jspbEncodingOptions ?? Conformance_JspbEncodingConfig()}
set {_jspbEncodingOptions = newValue}
}
/// Returns true if `jspbEncodingOptions` has been explicitly set.
var hasJspbEncodingOptions: Bool {return _storage._jspbEncodingOptions != nil}
var hasJspbEncodingOptions: Bool {return self._jspbEncodingOptions != nil}
/// Clears the value of `jspbEncodingOptions`. Subsequent reads from it will return its default value.
mutating func clearJspbEncodingOptions() {_uniqueStorage()._jspbEncodingOptions = nil}
mutating func clearJspbEncodingOptions() {self._jspbEncodingOptions = nil}

/// This can be used in json and text format. If true, testee should print
/// unknown fields instead of ignore. This feature is optional.
var printUnknownFields: Bool {
get {return _storage._printUnknownFields}
set {_uniqueStorage()._printUnknownFields = newValue}
}
var printUnknownFields: Bool = false

var unknownFields = SwiftProtobuf.UnknownStorage()

@@ -302,7 +287,7 @@ struct Conformance_ConformanceRequest {

init() {}

fileprivate var _storage = _StorageClass.defaultInstance
fileprivate var _jspbEncodingOptions: Conformance_JspbEncodingConfig? = nil
}

/// Represents a single test case's output.
@@ -519,123 +504,81 @@ extension Conformance_ConformanceRequest: SwiftProtobuf.Message, SwiftProtobuf._
9: .standard(proto: "print_unknown_fields"),
]

fileprivate class _StorageClass {
var _payload: Conformance_ConformanceRequest.OneOf_Payload?
var _requestedOutputFormat: Conformance_WireFormat = .unspecified
var _messageType: String = String()
var _testCategory: Conformance_TestCategory = .unspecifiedTest
var _jspbEncodingOptions: Conformance_JspbEncodingConfig? = nil
var _printUnknownFields: Bool = false

static let defaultInstance = _StorageClass()

private init() {}

init(copying source: _StorageClass) {
_payload = source._payload
_requestedOutputFormat = source._requestedOutputFormat
_messageType = source._messageType
_testCategory = source._testCategory
_jspbEncodingOptions = source._jspbEncodingOptions
_printUnknownFields = source._printUnknownFields
}
}

fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}

mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1:
if _storage._payload != nil {try decoder.handleConflictingOneOf()}
var v: Data?
try decoder.decodeSingularBytesField(value: &v)
if let v = v {_storage._payload = .protobufPayload(v)}
case 2:
if _storage._payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {_storage._payload = .jsonPayload(v)}
case 3: try decoder.decodeSingularEnumField(value: &_storage._requestedOutputFormat)
case 4: try decoder.decodeSingularStringField(value: &_storage._messageType)
case 5: try decoder.decodeSingularEnumField(value: &_storage._testCategory)
case 6: try decoder.decodeSingularMessageField(value: &_storage._jspbEncodingOptions)
case 7:
if _storage._payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {_storage._payload = .jspbPayload(v)}
case 8:
if _storage._payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {_storage._payload = .textPayload(v)}
case 9: try decoder.decodeSingularBoolField(value: &_storage._printUnknownFields)
default: break
}
while let fieldNumber = try decoder.nextFieldNumber() {
switch fieldNumber {
case 1:
if self.payload != nil {try decoder.handleConflictingOneOf()}
var v: Data?
try decoder.decodeSingularBytesField(value: &v)
if let v = v {self.payload = .protobufPayload(v)}
case 2:
if self.payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {self.payload = .jsonPayload(v)}
case 3: try decoder.decodeSingularEnumField(value: &self.requestedOutputFormat)
case 4: try decoder.decodeSingularStringField(value: &self.messageType)
case 5: try decoder.decodeSingularEnumField(value: &self.testCategory)
case 6: try decoder.decodeSingularMessageField(value: &self._jspbEncodingOptions)
case 7:
if self.payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {self.payload = .jspbPayload(v)}
case 8:
if self.payload != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {self.payload = .textPayload(v)}
case 9: try decoder.decodeSingularBoolField(value: &self.printUnknownFields)
default: break
}
}
}

func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
switch _storage._payload {
case .protobufPayload(let v)?:
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
case .jsonPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
case nil: break
default: break
}
if _storage._requestedOutputFormat != .unspecified {
try visitor.visitSingularEnumField(value: _storage._requestedOutputFormat, fieldNumber: 3)
}
if !_storage._messageType.isEmpty {
try visitor.visitSingularStringField(value: _storage._messageType, fieldNumber: 4)
}
if _storage._testCategory != .unspecifiedTest {
try visitor.visitSingularEnumField(value: _storage._testCategory, fieldNumber: 5)
}
if let v = _storage._jspbEncodingOptions {
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
}
switch _storage._payload {
case .jspbPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 7)
case .textPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 8)
case nil: break
default: break
}
if _storage._printUnknownFields != false {
try visitor.visitSingularBoolField(value: _storage._printUnknownFields, fieldNumber: 9)
}
switch self.payload {
case .protobufPayload(let v)?:
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
case .jsonPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
case nil: break
default: break
}
if self.requestedOutputFormat != .unspecified {
try visitor.visitSingularEnumField(value: self.requestedOutputFormat, fieldNumber: 3)
}
if !self.messageType.isEmpty {
try visitor.visitSingularStringField(value: self.messageType, fieldNumber: 4)
}
if self.testCategory != .unspecifiedTest {
try visitor.visitSingularEnumField(value: self.testCategory, fieldNumber: 5)
}
if let v = self._jspbEncodingOptions {
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
}
switch self.payload {
case .jspbPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 7)
case .textPayload(let v)?:
try visitor.visitSingularStringField(value: v, fieldNumber: 8)
case nil: break
default: break
}
if self.printUnknownFields != false {
try visitor.visitSingularBoolField(value: self.printUnknownFields, fieldNumber: 9)
}
try unknownFields.traverse(visitor: &visitor)
}

static func ==(lhs: Conformance_ConformanceRequest, rhs: Conformance_ConformanceRequest) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._payload != rhs_storage._payload {return false}
if _storage._requestedOutputFormat != rhs_storage._requestedOutputFormat {return false}
if _storage._messageType != rhs_storage._messageType {return false}
if _storage._testCategory != rhs_storage._testCategory {return false}
if _storage._jspbEncodingOptions != rhs_storage._jspbEncodingOptions {return false}
if _storage._printUnknownFields != rhs_storage._printUnknownFields {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.payload != rhs.payload {return false}
if lhs.requestedOutputFormat != rhs.requestedOutputFormat {return false}
if lhs.messageType != rhs.messageType {return false}
if lhs.testCategory != rhs.testCategory {return false}
if lhs._jspbEncodingOptions != rhs._jspbEncodingOptions {return false}
if lhs.printUnknownFields != rhs.printUnknownFields {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
Loading