From b2eb88f7f69a3c4242343ff4dc0de8df557f7ae6 Mon Sep 17 00:00:00 2001 From: panxi Date: Sun, 24 Nov 2019 23:14:25 -0500 Subject: [PATCH] update array decoding method --- MVMCore/MVMCore/Models/Model/Model.swift | 14 +++++ .../MVMCore/Models/Model/ModelRegistry.swift | 59 +++++++++++-------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/MVMCore/MVMCore/Models/Model/Model.swift b/MVMCore/MVMCore/Models/Model/Model.swift index 44e1025..8e37837 100644 --- a/MVMCore/MVMCore/Models/Model/Model.swift +++ b/MVMCore/MVMCore/Models/Model/Model.swift @@ -12,5 +12,19 @@ public protocol Model: Codable { static var identifier: String { get } + static func mvmdecode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? + static func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? +} + +extension Model { + static public func mvmdecode(keyedContainer: KeyedDecodingContainer, codingKey: K) throws -> Self? { + let m = try keyedContainer.decodeIfPresent(self, forKey: codingKey) + return m + } + + static public func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? { + let m = try unkeyedContainer.decodeIfPresent(self) + return m + } } diff --git a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift index cd40a83..0b83a6f 100644 --- a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift +++ b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift @@ -24,28 +24,6 @@ public struct ModelRegistry { } } -extension UnkeyedDecodingContainer { - - public mutating func decodeUnKeyedIfPresent(_ type: T.Type, typeCodingKey: C) throws -> T? where T : Decodable { - let meta = try self.nestedContainer(keyedBy: C.self) - guard let type = try meta.decodeIfPresent(String.self, forKey: typeCodingKey) else { - return nil - } - - //get the type - guard let found = ModelRegistry.types[type] else { - throw ModelRegistry.Error.decoderErrorModelNotMapped - } - let model = try self.decode(found) - - guard let m = model as? T else { - throw ModelRegistry.Error.decoderError - } - return m - } - -} - extension KeyedDecodingContainer where Key: CodingKey { private enum TypeCodingKey: String, CodingKey { @@ -79,17 +57,46 @@ extension KeyedDecodingContainer where Key: CodingKey { throw ModelRegistry.Error.decoderErrorModelNotMapped } - //get the decoder for the propertyKey - let decoder = try self.superDecoder(forKey: codingKey) - //decode the type using the decoder - let model = try found.init(from: decoder) + let model = try found.mvmdecode(keyedContainer: self, codingKey: codingKey) guard let m = model as? T else { throw ModelRegistry.Error.decoderError } + return m } + + + public func decodeArrayIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: C) throws -> [Model]? { + + var unkeyedContainer = try nestedUnkeyedContainer(forKey: codingKey) + var otherUnkeyedContainer = try nestedUnkeyedContainer(forKey: codingKey) + var attributes = [Model.Type]() + while !unkeyedContainer.isAtEnd { + + let meta = try unkeyedContainer.nestedContainer(keyedBy: C.self) + guard let type = try meta.decodeIfPresent(String.self, forKey: typeCodingKey) else { + return nil + } + //get the type + guard let found = ModelRegistry.types[type] else { + throw ModelRegistry.Error.decoderErrorModelNotMapped + } + attributes.append(found) + } + + var i = 0 + var models = [Model]() + while !otherUnkeyedContainer.isAtEnd { + let foundModel = attributes[i] + if let model = try foundModel.mvmdecode(unkeyedContainer: &otherUnkeyedContainer) { + models.append(model) + } + i += 1 + } + return models.count > 0 ? models : nil + } }