diff --git a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift index 4c8cc15..2aa0256 100644 --- a/MVMCore/MVMCore/Models/Model/ModelRegistry.swift +++ b/MVMCore/MVMCore/Models/Model/ModelRegistry.swift @@ -75,22 +75,7 @@ extension KeyedDecodingContainer where Key: CodingKey { guard var container = try? nestedUnkeyedContainer(forKey: codingKey) else { return nil } - var models = [Model]() - var containerCopy = container - while !container.isAtEnd { - let nestedContainer = try container.nestedContainer(keyedBy: TypeKey.self) - if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) { - //get the type - guard let type = ModelRegistry.getType(for: identifier) else { - throw ModelRegistry.Error.decoderErrorModelNotMapped - } - //now get the decoder to use for the type - let decoder = try containerCopy.superDecoder() - let model = try type.init(from: decoder) - models.append(model) - } - } - return models + return try container.decodeModelsIfPresent(typeCodingKey: typeCodingKey) } /// Decodes an array of registered model based on the identifiers. @@ -100,6 +85,22 @@ extension KeyedDecodingContainer where Key: CodingKey { } return models } + + /// Decodes an array with arrays of models based on the identifiers, optional. + public func decodeModels2DIfPresent(codingKey: KeyedDecodingContainer.Key, typeCodingKey: TypeKey) throws -> [[Model]]? { + guard var container = try? nestedUnkeyedContainer(forKey: codingKey) else { + return nil + } + return try container.decodeModels2DIfPresent(typeCodingKey: typeCodingKey) + } + + /// Decodes an array with arrays of models based on the identifiers. + public func decodeModels2D(codingKey: KeyedDecodingContainer.Key, typeCodingKey: TypeKey) throws -> [[Model]] { + guard let models: [[Model]] = try decodeModels2DIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else { + throw ModelRegistry.Error.decoderErrorObjectNotPresent + } + return models + } } extension KeyedEncodingContainer where Key: CodingKey { @@ -131,4 +132,52 @@ extension KeyedEncodingContainer where Key: CodingKey { try model.encode(unkeyedContainer: &unkeyedContainer) } } + + /// Convenience function for encoding the container into a list of lists of Models. needs instance type as input paramaeter list + public mutating func encodeModels2D(_ list: [[Model]]?, forKey key:KeyedEncodingContainer.Key) throws { + guard let list = list else { return } + var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key) + for models in list { + var arrayunkeyedContainer = unkeyedContainer.nestedUnkeyedContainer() + for model in models { + try model.encode(unkeyedContainer: &arrayunkeyedContainer) + } + } + } +} + +extension UnkeyedDecodingContainer { + /// Decodes the container into a list of Models. + public mutating func decodeModelsIfPresent(typeCodingKey: TypeKey) throws -> [Model]? { + var models = [Model]() + var containerCopy = self + while !containerCopy.isAtEnd { + let nestedContainer = try containerCopy.nestedContainer(keyedBy: TypeKey.self) + if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) { + //get the type + guard let type = ModelRegistry.getType(for: identifier) else { + throw ModelRegistry.Error.decoderErrorModelNotMapped + } + //now get the decoder to use for the type + let decoder = try self.superDecoder() + let model = try type.init(from: decoder) + models.append(model) + } + } + return models + } + + /// Convenience function for decoding the container into a list of lists of Models. + public mutating func decodeModels2DIfPresent(typeCodingKey: TypeKey) throws -> [[Model]]? { + var modelLists = [[Model]]() + var containerCopy = self + while !containerCopy.isAtEnd { + var arraycontainerCopy = try containerCopy.nestedUnkeyedContainer() + guard let models = try arraycontainerCopy.decodeModelsIfPresent(typeCodingKey: typeCodingKey) else { + throw ModelRegistry.Error.decoderErrorModelNotMapped + } + modelLists.append(models) + } + return modelLists + } }