// // LanguageResource.swift // KeymanEngine // // Created by Joshua Horton on 8/16/19. // Copyright © 2019 SIL International. All rights reserved. // import Foundation public enum LanguageResourceType { case keyboard, lexicalModel } // Subclasses must implement Equatable; Swift doesn't like it directly on the root protocol. public protocol LanguageResourceFullID { var id: String { get } var languageID: String { get } var type: LanguageResourceType { get } } extension LanguageResourceFullID where Self: Equatable { public static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.id == rhs.id && lhs.languageID == rhs.languageID && lhs.type == rhs.type } } extension LanguageResourceFullID { var description: String { return "{\(type): {id = \(id), languageID=\(languageID)}}" } } // Alas, 'associatedtype' stuff isn't exactly generic, and it's impossible to wildcard. // So, this supports Swift's "type erasure" pattern, acting as a "wildcarded" // LanguageResource that doesn't care about the specific associatedtype(s) that // specific LanguageResources use. public protocol AnyLanguageResource { var id: String { get } var languageID: String { get } // Was not always tracked within KeymanEngine - is optional for legacy reasons. var packageID: String? { get } var fullID: LanguageResourceFullID { get } var version: String { get } // Used for generating QR codes. var sharableURL: String? { get } // Used during resource installation var fonts: [Font] { get } var sourceFilename: String { get } } // Necessary due to Swift details 'documented' at // https://stackoverflow.com/questions/42561685/why-cant-a-get-only-property-requirement-in-a-protocol-be-satisfied-by-a-proper public protocol LanguageResource: AnyLanguageResource { associatedtype FullID: LanguageResourceFullID where FullID: Equatable var typedFullID: FullID { get } } extension LanguageResource { // Thanks to https://stackoverflow.com/a/58774558 (on same thread mentioned above) // for this approach. public var fullID: LanguageResourceFullID { return typedFullID } } internal protocol KMPInitializableLanguageResource: LanguageResource { associatedtype Metadata: KMPResource init?(from metadata: Metadata, packageID: String, lgCode: String) }