-
Notifications
You must be signed in to change notification settings - Fork 142
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
Support SE-0166 Swift Archival & Serialization #43
Conversation
This is very exciting! |
Tests/YamsTests/EncoderTests.swift
Outdated
if let expectedYAML = yaml { | ||
XCTAssertEqual(expectedYAML, payload, "Produced YAML not identical to expected YAML.") | ||
if let expectedYAML = yamlString { | ||
let producedYAML = String(data: payload, encoding: .utf8)! // swiftlint:disable:this force_unwrapping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably skip the force unwrap here as I think that XCTAssertEqual
can take arguments of (String?, String)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup. But I prefer failing output as
XCTAssertEqual failed: ("{}
") is not equal to ("{ }
") - Produced YAML not identical to expected YAML.
to
XCTAssertEqual failed: ("Optional("{}\n")") is not equal to ("Optional("{ }\n")") - Produced YAML not identical to expected YAML.
Especially in long strings, I feel the former is easier to see.
2715695
to
4b80558
Compare
390b289
to
f87861f
Compare
108899e
to
bd6ca73
Compare
087a6fe
to
8cbfbf9
Compare
aa8763f
to
6ab910a
Compare
Tests/YamsTests/EncoderTests.swift
Outdated
// MARK: - Date Strategy Tests | ||
func testEncodingDate() { | ||
#if os(Linux) | ||
print("'Date' does not conform to 'Codable' on Linux yet.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, this is now fixed 🎉
7f64904
to
42727ed
Compare
Sorry for being late. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First round of review.
Sources/Yams/Constructor.swift
Outdated
@@ -185,50 +187,94 @@ extension Double: ScalarConstructible { | |||
} | |||
} | |||
|
|||
extension Float: ScalarConstructible { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it'd be possible to generalize this to the FloatingPoint
protocol? I ran into several issues while trying to do it, but if you can find a way, seems like that'd be pretty powerful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try.
Sources/Yams/Constructor.swift
Outdated
var scalar = node.scalar!.string | ||
switch scalar { | ||
case ".inf", ".Inf", ".INF", "+.inf", "+.Inf", "+.INF": | ||
return Float.infinity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can omit the type here and below: (return .infinity
, return -.infinity
, return .nan
). Same with the Double
implementation.
Sources/Yams/Constructor.swift
Outdated
} | ||
#else | ||
fileprivate init?(_ value: String) { | ||
self.init(value, radix: 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indentation
Sources/Yams/Encoder.swift
Outdated
|
||
// MARK: - CodingKey for `_UnkeyedEncodingContainer` and `superEncoders` | ||
|
||
struct _YAMLEncodingKey: CodingKey { // swiftlint:disable:this type_name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shares an implementation with _YAMLDecodingKey
. Why not merge them into a _YAMLCodingKey
?
Sources/Yams/Representer.swift
Outdated
} | ||
} | ||
|
||
extension Double: ScalarRepresentableCustomizedForCodable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to combine these two implementations:
diff --git a/Sources/Yams/Representer.swift b/Sources/Yams/Representer.swift
index 09e05f9..c79eb44 100644
--- a/Sources/Yams/Representer.swift
+++ b/Sources/Yams/Representer.swift
@@ -225,23 +225,25 @@ extension Date: ScalarRepresentableCustomizedForCodable {
}
}
-extension Double: ScalarRepresentableCustomizedForCodable {
+extension Double: ScalarRepresentableCustomizedForCodable {}
+extension Float: ScalarRepresentableCustomizedForCodable {}
+
+extension FloatingPoint where Self: CVarArg {
public func representedForCodable() -> Node {
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
- return Node(formattedStringForCodable, Tag(.float))
- #else
+#if os(Linux)
return Node(doubleFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-"), Tag(.float))
- #endif
+#else
+ return Node(formattedStringForCodable, Tag(.float))
+#endif
}
private var formattedStringForCodable: String {
// Since `NumberFormatter` creates a string with insufficient precision for Decode,
// it uses with `String(format:...)`
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(Linux)
+ let DBL_DECIMAL_DIG = 9
+#endif
let string = String(format: "%.*g", DBL_DECIMAL_DIG, self)
- #else
- let string = String(format: "%.*g", 9, self)
- #endif
// "%*.g" does not use scientific notation if the exponent is less than –4.
// So fallback to using `NumberFormatter` if string does not uses scientific notation.
guard string.lazy.suffix(5).contains("e") else {
@@ -251,30 +253,4 @@ extension Double: ScalarRepresentableCustomizedForCodable {
}
}
-extension Float: ScalarRepresentableCustomizedForCodable {
- public func representedForCodable() -> Node {
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
- return Node(formattedStringForCodable, Tag(.float))
- #else
- return Node(floatFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-"), Tag(.float))
- #endif
- }
-
- private var formattedStringForCodable: String {
- // Since `NumberFormatter` creates a string with insufficient precision for Decode,
- // it uses with `String(format:...)`
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
- let string = String(format: "%.*g", FLT_DECIMAL_DIG, self)
- #else
- let string = String(format: "%.*g", 9, self)
- #endif
- // "%*.g" does not use scientific notation if the exponent is less than –4.
- // So fallback to using `NumberFormatter` if string does not uses scientific notation.
- guard string.lazy.suffix(6).contains("e") else {
- return floatFormatter.string(for: self)!.replacingOccurrences(of: "+-", with: "-")
- }
- return string
- }
-}
-
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for patch.
By applying this, I noticed that my commits has mistake:
+#if os(Linux)
+ let DBL_DECIMAL_DIG = 9
+#endif
DBL_DECIMAL_DIG
should be 17
.
That caused errors that fixed on 587c382.
_testRoundTrip(of: numbers, expectedYAML: "- 4\n- 8\n- 15\n- 16\n- 23\n- 42\n") | ||
} | ||
|
||
func testEncodingTopLevelStructuredSingleClass() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is flaky on Linux in my testing, where the order of keys doesn't appear to be stable across invocations.
EncoderTests.testEncodingTopLevelStructuredSingleClass : XCTAssertEqual failed: ("localhost:
relative: http://127.0.0.1
Apple:
relative: http://apple.com
") is not equal to ("Apple:
relative: http://apple.com
localhost:
relative: http://127.0.0.1
") - Produced YAML not identical to expected YAML.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add sortedKeys
option to Emitter.Options
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be PR against master.
I should say that this is super exciting. I think we'll be able to point to this to demonstrate a good implementation of Swift 4's custom encoders when this merges. |
Thank you for reviews! FYI, I opened a custom encoder implementation of Swift 4 that I created when refactoring this PR. |
Double and Float are now encoded with sufficient precision for decoding.
…ted only on Apple platforms
Some types already be changed.
Decoding 'Date' has issue on Linux with nanoseconds. https://bugs.swift.org/browse/SR-6223
For stabilizing the test on Linux.
b3ab975
to
697b6d7
Compare
Is this approved? |
Yes! 🎉 |
Thanks! 🙏 |
Support SE-0166 Swift Archival & Serialization
Fixes #38
This uses local built toolchain https://github.com/norio-nomura/swift-dev/releases/tag/20170501aTODOs for merging:
[ ] Add text encoding detection toYAMLDecoder.decode(_:from:)