Files

83 lines
2.8 KiB
Swift

import Foundation
public struct ExploreKind: Codable, Hashable, Identifiable, Sendable {
public var title: String
public var url: String?
public var type: String
public var action: String?
public var chars: [String?]?
public var defaultValue: String?
public var id: String { "\(title)\u{0}\(url ?? "")" }
public var navigableURL: String? {
guard type.caseInsensitiveCompare("url") == .orderedSame,
let value = url?.trimmingCharacters(in: .whitespacesAndNewlines),
!value.isEmpty else { return nil }
return value
}
enum CodingKeys: String, CodingKey {
case title, url, type, action, chars
case defaultValue = "default"
}
public init(
title: String,
url: String? = nil,
type: String = "url",
action: String? = nil,
chars: [String?]? = nil,
defaultValue: String? = nil
) {
self.title = title
self.url = url
self.type = type
self.action = action
self.chars = chars
self.defaultValue = defaultValue
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
title = values.lossyString(forKey: .title) ?? ""
url = values.lossyString(forKey: .url)
type = values.lossyString(forKey: .type) ?? "url"
action = values.lossyString(forKey: .action)
defaultValue = values.lossyString(forKey: .defaultValue)
if let decoded = try? values.decodeIfPresent([JSONValue].self, forKey: .chars) {
chars = decoded.map { value in
if case .null = value { return nil }
return value.stringValue
}
} else if let scalar = values.lossyString(forKey: .chars) {
chars = [scalar]
} else {
chars = nil
}
}
}
private extension KeyedDecodingContainer where Key == ExploreKind.CodingKeys {
func lossyString(forKey key: Key) -> String? {
guard contains(key), (try? decodeNil(forKey: key)) != true else { return nil }
if let value = try? decode(String.self, forKey: key) { return value }
if let value = try? decode(Bool.self, forKey: key) { return String(value) }
if let value = try? decode(Int64.self, forKey: key) { return String(value) }
if let value = try? decode(Double.self, forKey: key) {
return value.rounded() == value ? String(format: "%.0f", value) : String(value)
}
return nil
}
}
public struct ExploreKindsReport: Sendable {
public var kinds: [ExploreKind]
public var diagnostics: [RuleDiagnostic]
public init(kinds: [ExploreKind] = [], diagnostics: [RuleDiagnostic] = []) {
self.kinds = kinds
self.diagnostics = diagnostics
}
}