You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
Connect4/Persistance/Sources/Persistance/Rules.swift

96 lines
3.0 KiB

import Model
public struct CodableRulesWrapper: Codable {
public let rules: any Rules
public init(of rules: any Rules) {
self.rules = rules
}
public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: EnumCommonCodingKeys.self)
self.rules = try (try container.decode(RulesTypes.self, forKey: .type)).decodeRules(from: decoder)
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: EnumCommonCodingKeys.self)
let type = self.rules.type
try container.encode(type, forKey: .type)
try (self.rules as! Encodable).encode(to: encoder)
}
}
extension RulesTypes: CodingKey, Codable {
public init(from decoder: any Decoder) throws {
self = (try CodableEnum<Self>(from: decoder)).variant
}
public func encode(to encoder: any Encoder) throws {
try CodableEnum(of: self).encode(to: encoder)
}
public func decodeRules(from decoder: any Decoder) throws -> any Rules {
switch self {
case .FourInARow: try FourInARowRules(from: decoder)
case .TicTacToe: try TicTacToeRules(from: decoder)
}
}
}
private enum CommonRulesCodingKeys: CodingKey {
case minAligned
}
extension FourInARowRules: Codable {
public init(from decoder: any Decoder) throws {
guard let context = decoder.userInfo[.gameDecodingContext] as? CodableContext else {
throw DeError.CodableContext
}
let container = try decoder.container(keyedBy: CommonRulesCodingKeys.self)
guard let zelf = Self.init(
columns: context.board!.columns,
rows: context.board!.rows,
minAligned: try container.decode(Int.self, forKey: .minAligned),
players: context.players!
) else {
throw DeError.InitializationFailed
}
self = zelf
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CommonRulesCodingKeys.self)
try container.encode(self.minAligned, forKey: .minAligned)
}
}
extension TicTacToeRules: Codable {
public init(from decoder: any Decoder) throws {
guard let context = decoder.userInfo[.gameDecodingContext] as? CodableContext else {
throw DeError.CodableContext
}
let container = try decoder.container(keyedBy: CommonRulesCodingKeys.self)
guard let zelf = Self.init(
columns: context.board!.columns,
rows: context.board!.rows,
minAligned: try container.decode(Int.self, forKey: .minAligned),
players: context.players!
) else {
throw DeError.InitializationFailed
}
self = zelf
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CommonRulesCodingKeys.self)
try container.encode(self.minAligned, forKey: .minAligned)
}
}