From 1852e022961f28c765810817a6e66b7513a8b4e0 Mon Sep 17 00:00:00 2001 From: Andreas Karlsson Date: Sun, 1 Jun 2025 16:30:43 -0700 Subject: [PATCH 1/2] Fix compilation issue --- Sources/FITS/HDU/HEADER/HDUValue.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/FITS/HDU/HEADER/HDUValue.swift b/Sources/FITS/HDU/HEADER/HDUValue.swift index 5d2174d..6336fd5 100644 --- a/Sources/FITS/HDU/HEADER/HDUValue.swift +++ b/Sources/FITS/HDU/HEADER/HDUValue.swift @@ -106,7 +106,7 @@ extension HDUValue { } } - public static func ==(lhs: HDUValue, rhs: T?) -> Bool { + public static func ==(lhs: Self, rhs: T?) -> Bool { guard type(of: lhs) == T.self else { return false } if let right = rhs { return lhs.hashable == right.hashable @@ -115,7 +115,7 @@ extension HDUValue { } } - public static func ==(lhs: T?, rhs: HDUValue) -> Bool { + public static func ==(lhs: T?, rhs: Self) -> Bool { guard T.self == type(of: rhs) else { return false } if let left = lhs { return left.hashable == rhs.hashable @@ -124,12 +124,12 @@ extension HDUValue { } } - public static func ==(lhs: HDUValue, rhs: HDUValue) -> Bool { + public static func ==(lhs: Self, rhs: Self) -> Bool { guard type(of: lhs) == type(of: rhs) else { return false } return lhs.hashable == rhs.hashable } - public static func !=(lhs: HDUValue, rhs: HDUValue) -> Bool { + public static func !=(lhs: Self, rhs: Self) -> Bool { guard type(of: lhs) == type(of: rhs) else { return false } return lhs.hashable != rhs.hashable } From 5419a16d2dfa945caaa95402650811ac7c8cb6fc Mon Sep 17 00:00:00 2001 From: Andreas Karlsson Date: Sat, 28 Mar 2026 09:37:21 -0700 Subject: [PATCH 2/2] Fix Swift compilation issue --- .gitignore | 1 + Sources/FITS/ASCIITABLE/TDISP.swift | 48 ++++++++++++++++++---- Sources/FITS/ASCIITABLE/TFIELD.A.swift | 2 +- Sources/FITS/ASCIITABLE/TFIELD.E.swift | 2 +- Sources/FITS/ASCIITABLE/TFIELD.F.swift | 2 +- Sources/FITS/ASCIITABLE/TFIELD.I.swift | 2 +- Sources/FITS/ASCIITABLE/TFORM.swift | 17 +++++++- Sources/FITS/BINTABLE/BDISP.swift | 50 ++++++++++++++++++----- Sources/FITS/BINTABLE/BFORM.swift | 18 +++++++- Sources/FITS/BITPIX.swift | 4 ++ Sources/FITS/HDU/HEADER/HDUValue.swift | 12 +++--- Sources/FITS/HDU/HEADER/HeaderBlock.swift | 21 ++++++++-- Sources/FITS/TABLE/Displayable.swift | 8 +++- 13 files changed, 151 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 7af9aa5..ee39d49 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /Packages /*.xcodeproj xcuserdata/ +.claude/settings.local.json diff --git a/Sources/FITS/ASCIITABLE/TDISP.swift b/Sources/FITS/ASCIITABLE/TDISP.swift index 31c713e..3d4ee51 100644 --- a/Sources/FITS/ASCIITABLE/TDISP.swift +++ b/Sources/FITS/ASCIITABLE/TDISP.swift @@ -29,8 +29,38 @@ import Foundation w is the width in characters of displayed values, m is the minimum number of digits displayed, d is the number of digits to right of decimal, and e is number of digits in exponent. The .m and Ee fields are optional. */ -public enum TDISP : DISP { - +public enum TDISP : DISP, Equatable { + + private static func optionalEqual(_ a: Int?, _ b: Int?) -> Bool { + switch (a, b) { + case (.some(let x), .some(let y)): return x == y + case (.none, .none): return true + default: return false + } + } + + public static func ==(lhs: TDISP, rhs: TDISP) -> Bool { + switch (lhs, rhs) { + case (.A(let a), .A(let b)): + return a == b + case (.I(let w1, let m1), .I(let w2, let m2)), + (.B(let w1, let m1), .B(let w2, let m2)), + (.O(let w1, let m1), .O(let w2, let m2)), + (.Z(let w1, let m1), .Z(let w2, let m2)): + return w1 == w2 && optionalEqual(m1, m2) + case (.F(let w1, let d1), .F(let w2, let d2)), + (.EN(let w1, let d1), .EN(let w2, let d2)), + (.ES(let w1, let d1), .ES(let w2, let d2)): + return w1 == w2 && d1 == d2 + case (.E(let w1, let d1, let e1), .E(let w2, let d2, let e2)), + (.G(let w1, let d1, let e1), .G(let w2, let d2, let e2)), + (.D(let w1, let d1, let e1), .D(let w2, let d2, let e2)): + return w1 == w2 && d1 == d2 && optionalEqual(e1, e2) + default: + return false + } + } + /// Character case A(w: Int) @@ -152,25 +182,25 @@ public enum TDISP : DISP { case .A(let w): return "A\(w)" case .I(let w, let m): - return "I\(w)" + ((m != nil) ? ".\(m!)" : "") + return "I\(w)" + (m.map { ".\($0)" } ?? "") case .B(let w, let m): - return "B\(w)" + ((m != nil) ? ".\(m!)" : "") + return "B\(w)" + (m.map { ".\($0)" } ?? "") case .O(let w, let m): - return "O\(w)" + ((m != nil) ? ".\(m!)" : "") + return "O\(w)" + (m.map { ".\($0)" } ?? "") case .Z(let w, let m): - return "Z\(w)" + ((m != nil) ? ".\(m!)" : "") + return "Z\(w)" + (m.map { ".\($0)" } ?? "") case .F(let w, let d): return "F\(w).\(d)" case .E(let w, let d, let e): - return "E\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "E\(w).\(d)" + (e.map { "e\($0)" } ?? "") case .ES(let w, let d): return "ES\(w).\(d)" case .EN(let w, let d): return "EN\(w).\(d)" case .G(let w, let d, let e): - return "G\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "G\(w).\(d)" + (e.map { "e\($0)" } ?? "") case .D(let w, let d, let e): - return "D\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "D\(w).\(d)" + (e.map { "e\($0)" } ?? "") } } } diff --git a/Sources/FITS/ASCIITABLE/TFIELD.A.swift b/Sources/FITS/ASCIITABLE/TFIELD.A.swift index 7fa5c7f..a6079d2 100644 --- a/Sources/FITS/ASCIITABLE/TFIELD.A.swift +++ b/Sources/FITS/ASCIITABLE/TFIELD.A.swift @@ -73,7 +73,7 @@ extension TFIELD { } override public var description: String{ - return val != nil ? "\(val!)" : "-/-" + return val.map { "\($0)" } ?? "-/-" } } diff --git a/Sources/FITS/ASCIITABLE/TFIELD.E.swift b/Sources/FITS/ASCIITABLE/TFIELD.E.swift index 26c7583..46adf1c 100644 --- a/Sources/FITS/ASCIITABLE/TFIELD.E.swift +++ b/Sources/FITS/ASCIITABLE/TFIELD.E.swift @@ -73,7 +73,7 @@ extension TFIELD { } override public var description: String { - return val != nil ? "\(val!)" : "-/-" + return val.map { "\($0)" } ?? "-/-" } } } diff --git a/Sources/FITS/ASCIITABLE/TFIELD.F.swift b/Sources/FITS/ASCIITABLE/TFIELD.F.swift index ab17764..dd4168a 100644 --- a/Sources/FITS/ASCIITABLE/TFIELD.F.swift +++ b/Sources/FITS/ASCIITABLE/TFIELD.F.swift @@ -73,7 +73,7 @@ extension TFIELD { } override public var description: String { - return val != nil ? "\(val!)" : "-/-" + return val.map { "\($0)" } ?? "-/-" } } } diff --git a/Sources/FITS/ASCIITABLE/TFIELD.I.swift b/Sources/FITS/ASCIITABLE/TFIELD.I.swift index 9dce9af..d96c6cb 100644 --- a/Sources/FITS/ASCIITABLE/TFIELD.I.swift +++ b/Sources/FITS/ASCIITABLE/TFIELD.I.swift @@ -79,7 +79,7 @@ extension TFIELD { } override public var description: String { - return val != nil ? "\(val!)" : "-/-" + return val.map { "\($0)" } ?? "-/-" } } } diff --git a/Sources/FITS/ASCIITABLE/TFORM.swift b/Sources/FITS/ASCIITABLE/TFORM.swift index 5920775..2482624 100644 --- a/Sources/FITS/ASCIITABLE/TFORM.swift +++ b/Sources/FITS/ASCIITABLE/TFORM.swift @@ -23,8 +23,21 @@ */ import Foundation -public enum TFORM : FORM { - +public enum TFORM : FORM, Equatable { + + public static func ==(lhs: TFORM, rhs: TFORM) -> Bool { + switch (lhs, rhs) { + case (.A(let a), .A(let b)), (.I(let a), .I(let b)): + return a == b + case (.F(let w1, let d1), .F(let w2, let d2)), + (.E(let w1, let d1), .E(let w2, let d2)), + (.D(let w1, let d1), .D(let w2, let d2)): + return w1 == w2 && d1 == d2 + default: + return false + } + } + /// Character case A(w: Int) diff --git a/Sources/FITS/BINTABLE/BDISP.swift b/Sources/FITS/BINTABLE/BDISP.swift index 126e41c..d9d4dea 100644 --- a/Sources/FITS/BINTABLE/BDISP.swift +++ b/Sources/FITS/BINTABLE/BDISP.swift @@ -26,10 +26,40 @@ import Foundation /** Valid TDISPn format values in BINTABLE extensions. */ -public enum BDISP : DISP { - +public enum BDISP : DISP, Equatable { + + private static func optionalEqual(_ a: Int?, _ b: Int?) -> Bool { + switch (a, b) { + case (.some(let x), .some(let y)): return x == y + case (.none, .none): return true + default: return false + } + } + + public static func ==(lhs: BDISP, rhs: BDISP) -> Bool { + switch (lhs, rhs) { + case (.A(let a), .A(let b)), (.L(let a), .L(let b)): + return a == b + case (.I(let w1, let m1), .I(let w2, let m2)), + (.B(let w1, let m1), .B(let w2, let m2)), + (.O(let w1, let m1), .O(let w2, let m2)), + (.Z(let w1, let m1), .Z(let w2, let m2)): + return w1 == w2 && optionalEqual(m1, m2) + case (.F(let w1, let d1), .F(let w2, let d2)), + (.EN(let w1, let d1), .EN(let w2, let d2)), + (.ES(let w1, let d1), .ES(let w2, let d2)): + return w1 == w2 && d1 == d2 + case (.E(let w1, let d1, let e1), .E(let w2, let d2, let e2)), + (.G(let w1, let d1, let e1), .G(let w2, let d2, let e2)), + (.D(let w1, let d1, let e1), .D(let w2, let d2, let e2)): + return w1 == w2 && d1 == d2 && optionalEqual(e1, e2) + default: + return false + } + } + /// Character - case A(w: Int) + case A(w: Int) /// Logical case L(w: Int) @@ -159,25 +189,25 @@ public enum BDISP : DISP { case .L(let w): return "L\(w)" case .I(let w, let m): - return "I\(w)" + ((m != nil) ? ".\(m!)" : "") + return "I\(w)" + (m.map { ".\($0)" } ?? "") case .B(let w, let m): - return "B\(w)" + ((m != nil) ? ".\(m!)" : "") + return "B\(w)" + (m.map { ".\($0)" } ?? "") case .O(let w, let m): - return "O\(w)" + ((m != nil) ? ".\(m!)" : "") + return "O\(w)" + (m.map { ".\($0)" } ?? "") case .Z(let w, let m): - return "Z\(w)" + ((m != nil) ? ".\(m!)" : "") + return "Z\(w)" + (m.map { ".\($0)" } ?? "") case .F(let w, let d): return "F\(w).\(d)" case .E(let w, let d, let e): - return "E\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "E\(w).\(d)" + (e.map { "e\($0)" } ?? "") case .ES(let w, let d): return "ES\(w).\(d)" case .EN(let w, let d): return "EN\(w).\(d)" case .G(let w, let d, let e): - return "G\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "G\(w).\(d)" + (e.map { "e\($0)" } ?? "") case .D(let w, let d, let e): - return "D\(w).\(d)" + ((e != nil) ? "e\(e!)" : "") + return "D\(w).\(d)" + (e.map { "e\($0)" } ?? "") } } } diff --git a/Sources/FITS/BINTABLE/BFORM.swift b/Sources/FITS/BINTABLE/BFORM.swift index 94a693b..28c01fb 100644 --- a/Sources/FITS/BINTABLE/BFORM.swift +++ b/Sources/FITS/BINTABLE/BFORM.swift @@ -24,7 +24,23 @@ import Foundation -public enum BFORM : FORM { +public enum BFORM : FORM, Equatable { + + public static func ==(lhs: BFORM, rhs: BFORM) -> Bool { + switch (lhs, rhs) { + case (.L(let a), .L(let b)), (.X(let a), .X(let b)), (.B(let a), .B(let b)), + (.I(let a), .I(let b)), (.J(let a), .J(let b)), (.K(let a), .K(let b)), + (.A(let a), .A(let b)), (.E(let a), .E(let b)), (.D(let a), .D(let b)), + (.C(let a), .C(let b)), (.M(let a), .M(let b)), + (.PL(let a), .PL(let b)), (.PX(let a), .PX(let b)), (.PB(let a), .PB(let b)), + (.PI(let a), .PI(let b)), (.PJ(let a), .PJ(let b)), (.PK(let a), .PK(let b)), + (.PA(let a), .PA(let b)), (.PE(let a), .PE(let b)), (.PC(let a), .PC(let b)), + (.QD(let a), .QD(let b)), (.QM(let a), .QM(let b)): + return a == b + default: + return false + } + } case L(r: Int) case X(r: Int) diff --git a/Sources/FITS/BITPIX.swift b/Sources/FITS/BITPIX.swift index 56a0cd3..aa68cdd 100644 --- a/Sources/FITS/BITPIX.swift +++ b/Sources/FITS/BITPIX.swift @@ -90,4 +90,8 @@ public enum BITPIX : Int { case .FLOAT64: return MemoryLayout.size } } + + public static func ==(lhs: BITPIX, rhs: BITPIX) -> Bool { + lhs.rawValue == rhs.rawValue + } } diff --git a/Sources/FITS/HDU/HEADER/HDUValue.swift b/Sources/FITS/HDU/HEADER/HDUValue.swift index 6336fd5..dc03f63 100644 --- a/Sources/FITS/HDU/HEADER/HDUValue.swift +++ b/Sources/FITS/HDU/HEADER/HDUValue.swift @@ -89,7 +89,7 @@ struct AnyHDUValue { } extension HDUValue { - + public static func ==(lhs: HDUValue?, rhs: Self) -> Bool { if let left = lhs { return left.hashable == rhs.hashable @@ -97,7 +97,7 @@ extension HDUValue { return false } } - + public static func ==(lhs: Self, rhs: HDUValue?) -> Bool { if let right = rhs { return lhs.hashable == right.hashable @@ -105,7 +105,7 @@ extension HDUValue { return false } } - + public static func ==(lhs: Self, rhs: T?) -> Bool { guard type(of: lhs) == T.self else { return false } if let right = rhs { @@ -114,7 +114,7 @@ extension HDUValue { return false } } - + public static func ==(lhs: T?, rhs: Self) -> Bool { guard T.self == type(of: rhs) else { return false } if let left = lhs { @@ -136,11 +136,11 @@ extension HDUValue { } extension HDUValue where Self : Hashable { - + public func hash(hasher: inout Hasher){ hasher.combine(self) } - + public var hashable : AnyHashable { AnyHashable(self) } diff --git a/Sources/FITS/HDU/HEADER/HeaderBlock.swift b/Sources/FITS/HDU/HEADER/HeaderBlock.swift index 6fa833e..956aa62 100644 --- a/Sources/FITS/HDU/HEADER/HeaderBlock.swift +++ b/Sources/FITS/HDU/HEADER/HeaderBlock.swift @@ -70,7 +70,9 @@ public final class HeaderBlock { /// Containts only a comment but neither a keyword nor a value public var isHeadline : Bool { - return keyword.isEmpty && value == nil && comment != nil + if value != nil { return false } + guard let _ = comment else { return false } + return keyword.isEmpty } /// Containts the `HDUKeyworld.XTENSION` @@ -87,7 +89,13 @@ extension HeaderBlock : Hashable { } public static func ==(lhs : HeaderBlock, rhs : HeaderBlock) -> Bool { - return lhs.keyword == rhs.keyword && lhs.value?.hashable == rhs.value?.hashable && lhs.comment == rhs.comment + guard lhs.keyword == rhs.keyword else { return false } + guard lhs.value?.hashable == rhs.value?.hashable else { return false } + switch (lhs.comment, rhs.comment) { + case let (l?, r?): return l == r + case (nil, nil): return true + default: return false + } } } @@ -99,7 +107,14 @@ extension HeaderBlock : CustomStringConvertible { if let string = String(data: data, encoding: .ascii){ return string } else { - return "\(keyword) \(value != nil ? "= "+value!.description : "") \(value != nil && comment != nil ? "/ "+comment! : comment ?? "")" + let valueStr = value.map { "= " + $0.description } ?? "" + let commentStr: String + if value != nil, let c = comment { + commentStr = "/ " + c + } else { + commentStr = comment ?? "" + } + return "\(keyword) \(valueStr) \(commentStr)" } } } diff --git a/Sources/FITS/TABLE/Displayable.swift b/Sources/FITS/TABLE/Displayable.swift index ffa9795..ad5673d 100644 --- a/Sources/FITS/TABLE/Displayable.swift +++ b/Sources/FITS/TABLE/Displayable.swift @@ -59,7 +59,13 @@ extension _Displayable { /// compute a string for a missing value func empty(_ form: FORM?, _ null: String?, _ fallback: String) -> String { - return null != nil ? null! : (form != nil ? String(repeating: " ", count: form!.length) : fallback) + if let null = null { + return null + } else if let form = form { + return String(repeating: " ", count: form.length) + } else { + return fallback + } } }