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

Remove asserts in Constructor #94

Merged
merged 2 commits into from
Jan 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 26 additions & 30 deletions Sources/Yams/Constructor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public final class Constructor {
}
switch node {
case .scalar:
return String._construct(from: node)
return String.construct(from: node)!
case .mapping:
return [AnyHashable: Any]._construct_mapping(from: node)
case .sequence:
Expand Down Expand Up @@ -66,8 +66,8 @@ public protocol ScalarConstructible {

extension Bool: ScalarConstructible {
public static func construct(from node: Node) -> Bool? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
switch node.scalar!.string.lowercased() {
guard let string = node.scalar?.string else { return nil }
switch string.lowercased() {
case "true", "yes", "on":
return true
case "false", "no", "off":
Expand All @@ -80,29 +80,27 @@ extension Bool: ScalarConstructible {

extension Data: ScalarConstructible {
public static func construct(from node: Node) -> Data? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
let data = Data(base64Encoded: node.scalar!.string, options: .ignoreUnknownCharacters)
return data
guard let string = node.scalar?.string else { return nil }
return Data(base64Encoded: string, options: .ignoreUnknownCharacters)
}
}

extension Date: ScalarConstructible {
public static func construct(from node: Node) -> Date? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
let scalar = node.scalar!.string
guard let string = node.scalar?.string else { return nil }

let range = NSRange(location: 0, length: scalar.utf16.count)
guard let result = timestampPattern.firstMatch(in: scalar, options: [], range: range),
let range = NSRange(location: 0, length: string.utf16.count)
guard let result = timestampPattern.firstMatch(in: string, options: [], range: range),
result.range.location != NSNotFound else {
return nil
}
#if os(Linux) || swift(>=4.0)
let components = (1..<result.numberOfRanges).map {
scalar.substring(with: result.range(at: $0))
string.substring(with: result.range(at: $0))
}
#else
let components = (1..<result.numberOfRanges).map {
scalar.substring(with: result.rangeAt($0))
string.substring(with: result.rangeAt($0))
}
#endif

Expand Down Expand Up @@ -161,29 +159,30 @@ extension Float: ScalarConstructible {}

extension ScalarConstructible where Self: FloatingPoint & SexagesimalConvertible {
public static func construct(from node: Node) -> Self? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
var scalar = node.scalar!.string
switch scalar {
guard var string = node.scalar?.string else { return nil }
switch string {
case ".inf", ".Inf", ".INF", "+.inf", "+.Inf", "+.INF":
return .infinity
case "-.inf", "-.Inf", "-.INF":
return -Self.infinity
case ".nan", ".NaN", ".NAN":
return .nan
default:
scalar = scalar.replacingOccurrences(of: "_", with: "")
if scalar.contains(":") {
return Self(sexagesimal: scalar)
string = string.replacingOccurrences(of: "_", with: "")
if string.contains(":") {
return Self(sexagesimal: string)
}
return .create(from: scalar)
return .create(from: string)
}
}
}

extension FixedWidthInteger where Self: SexagesimalConvertible {
fileprivate static func _construct(from node: Node) -> Self? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
let scalarWithSign = node.scalar!.string.replacingOccurrences(of: "_", with: "")
guard let string = node.scalar?.string else { return nil }

let scalarWithSign = string.replacingOccurrences(of: "_", with: "")

if scalarWithSign == "0" {
return 0
}
Expand Down Expand Up @@ -227,18 +226,15 @@ extension UInt: ScalarConstructible {

extension String: ScalarConstructible {
public static func construct(from node: Node) -> String? {
return _construct(from: node)
}

fileprivate static func _construct(from node: Node) -> String {
// This will happen while `Dictionary.flatten_mapping()` if `node.tag.name` was `.value`
if case let .mapping(mapping) = node {
for (key, value) in mapping where key.tag.name == .value {
return _construct(from: value)
return construct(from: value)!
}
}
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
return node.scalar!.string

guard let string = node.scalar?.string else { return nil }
return string
}
}

Expand Down Expand Up @@ -267,7 +263,7 @@ extension Dictionary {
var dictionary = [AnyHashable: Any](minimumCapacity: mapping.count)
mapping.forEach {
// TODO: YAML supports keys other than str.
dictionary[String._construct(from: $0.key)] = node.tag.constructor.any(from: $0.value)
dictionary[String.construct(from: $0.key)!] = node.tag.constructor.any(from: $0.value)
}
return dictionary
}
Expand Down Expand Up @@ -314,7 +310,7 @@ extension Set {
public static func construct_set(from node: Node) -> Set<AnyHashable>? {
// TODO: YAML supports Hashable elements other than str.
assert(node.isMapping) // swiftlint:disable:next force_unwrapping
return Set<AnyHashable>(node.mapping!.map({ String._construct(from: $0.key) as AnyHashable }))
return Set<AnyHashable>(node.mapping!.map({ String.construct(from: $0.key)! as AnyHashable }))
// Explicitly declaring the generic parameter as `<AnyHashable>` above is required,
// because this is inside extension of `Set` and Swift 3.0.2 can't infer the type without that.
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/Yams/Decoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,14 @@ extension UInt8: ScalarConstructible {}

extension Decimal: ScalarConstructible {
public static func construct(from node: Node) -> Decimal? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
return Decimal(string: node.scalar!.string)
guard let string = node.scalar?.string else { return nil }
return Decimal(string: string)
}
}

extension URL: ScalarConstructible {
public static func construct(from node: Node) -> URL? {
assert(node.isScalar) // swiftlint:disable:next force_unwrapping
return URL(string: node.scalar!.string)
guard let string = node.scalar?.string else { return nil }
return URL(string: string)
}
}
43 changes: 42 additions & 1 deletion Tests/YamsTests/ConstructorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
"description": "The binary value above is a tiny arrow encoded as a gif image."
]
YamsAssertEqual(objects, expected)

XCTAssertNil(Data.construct(from: [Node("1"), Node("2")]))
}

func testBool() throws {
Expand All @@ -67,6 +69,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
]
]
YamsAssertEqual(objects, expected)

XCTAssertNil(Bool.construct(from: [Node("1"), Node("2")]))
}

func testFloat() throws {
Expand All @@ -89,6 +93,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
"not a number": Double.nan
]
YamsAssertEqual(objects, expected)

XCTAssertNil(Float.construct(from: [Node("1"), Node("2")]))
}

func testInt() throws {
Expand Down Expand Up @@ -127,6 +133,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
"canonicalMax": 9223372036854775807
]
YamsAssertEqual(objects, expected)

XCTAssertNil(Int.construct(from: [Node("1"), Node("2")]))
}

func testMap() throws {
Expand Down Expand Up @@ -237,6 +245,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
]
]
YamsAssertEqual(objects, expected)

XCTAssertNil(NSNull.construct(from: [Node("1"), Node("2")]))
}

func testOmap() throws {
Expand Down Expand Up @@ -362,6 +372,8 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length
"date (00:00:00Z)": timestamp( 0, 2002, 12, 14)
]
YamsAssertEqual(objects, expected)

XCTAssertNil(Date.construct(from: [Node("1"), Node("2")]))
}

func testTimestampWithNanosecond() throws {
Expand Down Expand Up @@ -406,6 +418,32 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length

YamsAssertEqual(objects, expected)
}

func testString() throws {
let example = """
one: two
three: four
"""
let objects = try Yams.load(yaml: example)
let expected: [String: Any] = [
"one": "two",
"three": "four"
]
YamsAssertEqual(objects, expected)

XCTAssertNil(String.construct(from: [Node("1"), Node("2")]))
}

func testDecimal() throws {
XCTAssertEqual(Decimal.construct(from: Node("1.2")), Decimal(string: "1.2")!)
XCTAssertNil(Decimal.construct(from: [Node("1"), Node("2")]))
}

func testURL() throws {
XCTAssertEqual(URL.construct(from: Node("http://www.google.com")), URL(string: "http://www.google.com")!)
XCTAssertEqual(URL.construct(from: Node("~/file.txt")), URL(string: "~/file.txt")!)
XCTAssertNil(URL.construct(from: [Node("1"), Node("2")]))
}
}

extension ConstructorTests {
Expand All @@ -424,7 +462,10 @@ extension ConstructorTests {
("testSeq", testSeq),
("testTimestamp", testTimestamp),
("testTimestampWithNanosecond", testTimestampWithNanosecond),
("testValue", testValue)
("testValue", testValue),
("testString", testString),
("testDecimal", testDecimal),
("testURL", testURL)
]
}
} // swiftlint:disable:this file_length