diff --git a/Sources/Yams/Constructor.swift b/Sources/Yams/Constructor.swift index 41b8a587..4120202c 100644 --- a/Sources/Yams/Constructor.swift +++ b/Sources/Yams/Constructor.swift @@ -530,8 +530,11 @@ public protocol SexagesimalConvertible: ExpressibleByIntegerLiteral { } private extension SexagesimalConvertible { - init(sexagesimal value: String) { - self = value.sexagesimal() + init?(sexagesimal value: String) { + guard let value = value.sexagesimal() as Self? else { + return nil + } + self = value } } @@ -575,7 +578,7 @@ extension Int64: SexagesimalConvertible {} extension UInt64: SexagesimalConvertible {} private extension String { - func sexagesimal() -> T where T: SexagesimalConvertible { + func sexagesimal() -> T? where T: SexagesimalConvertible { assert(contains(":")) var scalar = self @@ -589,7 +592,12 @@ private extension String { } else { sign = 1 } - let digits = scalar.components(separatedBy: ":").compactMap(T.create).reversed() + let components = scalar.components(separatedBy: ":") + let mappedComponents = components.compactMap(T.create) + guard mappedComponents.count == components.count else { + return nil + } + let digits = mappedComponents.reversed() let (_, value) = digits.reduce((1, 0) as (T, T)) { baseAndValue, digit in let value = baseAndValue.1 + (digit * baseAndValue.0) let base = baseAndValue.0 * 60 diff --git a/Tests/YamsTests/ConstructorTests.swift b/Tests/YamsTests/ConstructorTests.swift index 9f93039a..53b76d3b 100644 --- a/Tests/YamsTests/ConstructorTests.swift +++ b/Tests/YamsTests/ConstructorTests.swift @@ -515,6 +515,13 @@ class ConstructorTests: XCTestCase { // swiftlint:disable:this type_body_length XCTAssertEqual(nodes[1]["link with"]?[1]?["="], "library2.dll") XCTAssertEqual(nodes[1]["link with"]?[1]?["version"], "2.3") } + + func testStrictParsingSexagesimal() throws { + XCTAssertEqual(Int.construct(from: .init("12:34:56")), 45296) + XCTAssertEqual(Double.construct(from: .init("12:34:56.789")), 45296.789) + XCTAssertNil(Int.construct(from: .init("http://example.com"))) + XCTAssertNil(Double.construct(from: .init("http://example.com"))) + } } extension ConstructorTests {