Name changes and cleanup
This commit is contained in:
parent
4a05db9c9a
commit
fc108373cb
@ -12,33 +12,33 @@ public protocol Model: Codable {
|
||||
|
||||
static var identifier: String { get }
|
||||
|
||||
static func mvmdecode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, codingKey: K) throws -> Self?
|
||||
static func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self?
|
||||
/// Convenience function to decode to model using a keyed container.
|
||||
static func decode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, codingKey: K) throws -> Self?
|
||||
/// Convenience function to decode to model using an unkeyed container.
|
||||
static func decode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self?
|
||||
/// Convenience function to encode model using a keyed container.
|
||||
func encode<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, codingKey: K) throws
|
||||
/// Convenience function to encode model using an unkeyed container.
|
||||
func encode(unkeyedContainer: inout UnkeyedEncodingContainer) throws
|
||||
}
|
||||
|
||||
extension Model {
|
||||
static public func mvmdecode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, codingKey: K) throws -> Self? {
|
||||
static public func decode<K:CodingKey>(keyedContainer: KeyedDecodingContainer<K>, codingKey: K) throws -> Self? {
|
||||
let m = try keyedContainer.decodeIfPresent(self, forKey: codingKey)
|
||||
return m
|
||||
}
|
||||
|
||||
static public func mvmdecode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? {
|
||||
static public func decode(unkeyedContainer: inout UnkeyedDecodingContainer) throws -> Self? {
|
||||
let m = try unkeyedContainer.decodeIfPresent(self)
|
||||
return m
|
||||
}
|
||||
|
||||
static public func mvmencode<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, codingKey: K, model: Model) throws {
|
||||
guard let typedModel = model as? Self else {
|
||||
throw ModelRegistry.Error.encoderError
|
||||
}
|
||||
try keyedContainer.encode(typedModel, forKey: codingKey)
|
||||
public func encode<K:CodingKey>(keyedContainer: inout KeyedEncodingContainer<K>, codingKey: K) throws {
|
||||
try keyedContainer.encode(self, forKey: codingKey)
|
||||
}
|
||||
|
||||
static public func mvmencode(unkeyedContainer: inout UnkeyedEncodingContainer, model: Model) throws{
|
||||
guard let typedModel = model as? Self else {
|
||||
throw ModelRegistry.Error.encoderError
|
||||
}
|
||||
try unkeyedContainer.encode(typedModel)
|
||||
public func encode(unkeyedContainer: inout UnkeyedEncodingContainer) throws{
|
||||
try unkeyedContainer.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ public struct ModelRegistry {
|
||||
|
||||
fileprivate static var types = [String: Model.Type]()
|
||||
|
||||
/// Register the model.
|
||||
public static func register<M: Model>(_ type: M.Type) {
|
||||
types[M.identifier] = type
|
||||
}
|
||||
@ -31,8 +32,9 @@ public struct ModelRegistry {
|
||||
extension KeyedDecodingContainer where Key: CodingKey {
|
||||
|
||||
//MARK: - Decode
|
||||
public func decode<T, C:CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T {
|
||||
guard let model: Model = try decodeIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
|
||||
/// Decodes to a registered model based on the identifier
|
||||
public func decodeModel<T, C: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T {
|
||||
guard let model: Model = try decodeModelIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
|
||||
throw ModelRegistry.Error.decoderErrorObjectNotPresent
|
||||
}
|
||||
|
||||
@ -44,26 +46,27 @@ extension KeyedDecodingContainer where Key: CodingKey {
|
||||
}
|
||||
|
||||
//MARK: - DecodeIfPresent
|
||||
public func decodeIfPresent<T, C:CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T? {
|
||||
//get the type string
|
||||
var meta: KeyedDecodingContainer<C>?
|
||||
/// Decodes to a registered model based on the identifier, optional.
|
||||
public func decodeModelIfPresent<T, C: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> T? {
|
||||
//get the identifier string
|
||||
var container: KeyedDecodingContainer<C>?
|
||||
do {
|
||||
meta = try self.nestedContainer(keyedBy: C.self, forKey: codingKey)
|
||||
container = try nestedContainer(keyedBy: C.self, forKey: codingKey)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
guard let type = try meta?.decodeIfPresent(String.self, forKey: typeCodingKey) else {
|
||||
guard let identifier = try container?.decodeIfPresent(String.self, forKey: typeCodingKey) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
//get the type
|
||||
guard let found = ModelRegistry.types[type] else {
|
||||
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "Model not mapped: \(type)")
|
||||
guard let type = ModelRegistry.types[identifier] else {
|
||||
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "Model not mapped: \(identifier)")
|
||||
throw ModelRegistry.Error.decoderErrorModelNotMapped
|
||||
}
|
||||
|
||||
//decode the type using the decoder
|
||||
let model = try found.mvmdecode(keyedContainer: self, codingKey: codingKey)
|
||||
let model = try type.decode(keyedContainer: self, codingKey: codingKey)
|
||||
|
||||
guard let m = model as? T else {
|
||||
throw ModelRegistry.Error.decoderError
|
||||
@ -72,80 +75,70 @@ extension KeyedDecodingContainer where Key: CodingKey {
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
public func decodeArrayIfPresent<C:CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> [Model]? {
|
||||
var unkeyedContainer: UnkeyedDecodingContainer?
|
||||
do {
|
||||
unkeyedContainer = try nestedUnkeyedContainer(forKey: codingKey)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
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)
|
||||
}
|
||||
/// Decodes an array of registered model based on the identifiers, optional.
|
||||
public func decodeModelsIfPresent<C: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> [Model]? {
|
||||
var models = [Model]()
|
||||
var container = try nestedUnkeyedContainer(forKey: codingKey)
|
||||
var containerCopy = container
|
||||
|
||||
var i = 0
|
||||
var models = [Model]()
|
||||
while !otherUnkeyedContainer.isAtEnd {
|
||||
let foundModel = attributes[i]
|
||||
if let model = try foundModel.mvmdecode(unkeyedContainer: &otherUnkeyedContainer) {
|
||||
models.append(model)
|
||||
let count = container.count ?? 0
|
||||
|
||||
while !container.isAtEnd {
|
||||
if i < count {
|
||||
let nestedContainer = try container.nestedContainer(keyedBy: C.self)
|
||||
if let identifier = try nestedContainer.decodeIfPresent(String.self, forKey: typeCodingKey) {
|
||||
//get the type
|
||||
guard let type = ModelRegistry.types[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)
|
||||
}
|
||||
i+=1
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
return models
|
||||
return models.count > 0 ? models : nil
|
||||
}
|
||||
|
||||
public func decodeArray<C:CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> [Model] {
|
||||
guard let models: [Model] = try decodeArrayIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
|
||||
/// Decodes an array of registered model based on the identifiers.
|
||||
public func decodeModels<C: CodingKey>(codingKey: KeyedDecodingContainer<K>.Key, typeCodingKey: C) throws -> [Model] {
|
||||
guard let models: [Model] = try decodeModelsIfPresent(codingKey: codingKey, typeCodingKey: typeCodingKey) else {
|
||||
throw ModelRegistry.Error.decoderErrorObjectNotPresent
|
||||
}
|
||||
return models
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension KeyedEncodingContainer where Key: CodingKey {
|
||||
|
||||
public mutating func encodeIfPresent(_ value: Model?, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
||||
/// Encodes a model, optional.
|
||||
public mutating func encodeModelIfPresent(_ value: Model?, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
||||
if let v = value {
|
||||
let encoder = self.superEncoder(forKey: key)
|
||||
try v.encode(to: encoder)
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func encode(_ value: Model, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
||||
/// Encodes a model.
|
||||
public mutating func encodeModel(_ value: Model, forKey key: KeyedEncodingContainer<K>.Key) throws {
|
||||
let encoder = self.superEncoder(forKey: key)
|
||||
try value.encode(to: encoder)
|
||||
}
|
||||
|
||||
///need instance type as input paramaeter list
|
||||
public mutating func encodeArray(_ list:[Model], forKey key:KeyedEncodingContainer<K>.Key) throws {
|
||||
var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key)
|
||||
for model in list {
|
||||
let typeString = type(of: model).identifier
|
||||
let type = ModelRegistry.getType(for: typeString)
|
||||
try type?.mvmencode(unkeyedContainer: &unkeyedContainer, model: model)
|
||||
}
|
||||
/// Encodes an array of models
|
||||
public mutating func encodeModels(_ list: [Model], forKey key:KeyedEncodingContainer<K>.Key) throws {
|
||||
try encodeModelsIfPresent(list, forKey: key)
|
||||
}
|
||||
|
||||
public mutating func encodeArrayIfPresent(_ list:[Model]?, forKey key:KeyedEncodingContainer<K>.Key) throws {
|
||||
guard let models = list else { return }
|
||||
do {
|
||||
try self.encodeArray(models, forKey: key)
|
||||
} catch {
|
||||
return
|
||||
/// Encodes an array of models, optional, need instance type as input paramaeter list
|
||||
public mutating func encodeModelsIfPresent(_ list: [Model]?, forKey key:KeyedEncodingContainer<K>.Key) throws {
|
||||
guard let list = list else { return }
|
||||
var unkeyedContainer = self.nestedUnkeyedContainer(forKey: key)
|
||||
for model in list {
|
||||
try model.encode(unkeyedContainer: &unkeyedContainer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user