import CoreFoundation import Serialization import VGSL /// Deserialization for Field? extension [String: Any] { @inlinable func link(for key: String) -> String? { self["$" + key] as? String } @inlinable func getOptionalField( _ key: String, transform: (U) -> T? ) -> Field? { if let value: T = try? getOptionalField(key, transform: transform) { return .value(value) } if let link = link(for: key) { return .link(link) } return nil } @inlinable func getOptionalField(_ key: String) -> Field? { getOptionalField(key, transform: T.init(rawValue:)) } @inlinable func getOptionalField(_ key: String) -> Field? { getOptionalField(key, transform: { $0 as T }) } @inlinable func getOptionalField( _ key: String, templateToType: [TemplateName: String] ) -> Field? { getOptionalField( key, transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) } ) } } /// Deserializaton for Field<[T]> and [T] extension [String: Any] { @inlinable func getOptionalArray( _ key: String, transform: (U) throws -> T, validator: AnyArrayValueValidator? = nil ) -> Field<[T]>? { if let value: [T] = try? getOptionalArray( key, transform: transform, validator: validator ) { return .value(value) } return link(for: key).map { .link($0) } } @inlinable func getOptionalArray( _ key: String, transform: (U) -> T?, validator: AnyArrayValueValidator? = nil ) -> Field<[T]>? { getOptionalArray( key, transform: { (value: U) throws -> T in guard let result = transform(value) else { throw DeserializationError.generic } return result }, validator: validator ) } @inlinable func getOptionalArray(_ key: String) -> Field<[T]>? { getOptionalArray(key, transform: T.init(rawValue:)) } @inlinable func getOptionalArray( _ key: String, templateToType: [TemplateName: String] ) -> Field<[T]>? { getOptionalArray( key, transform: { (dict: Self) in try? T(dictionary: dict, templateToType: templateToType) } ) } } extension [String: Any] { @inlinable func getField( _ key: String, templateToType: [TemplateName: String] ) throws -> T { try getField( key, transform: { (dict: Self) in try T(dictionary: dict, templateToType: templateToType) } ) } } extension TemplatesContext { @inlinable func getArray( _ key: String, validator: AnyArrayValueValidator? = nil, type: T.Type ) -> DeserializationResult<[T.ResolvedValue]> { templateData.getArray( key, transform: makeTemplateDeserializer( templates: templates, templateToType: templateToType, type: type ), validator: validator ) } } @inlinable func deserialize( _ value: Any, templates: [TemplateName: Any], templateToType: [TemplateName: String], type: T.Type ) -> DeserializationResult { deserialize( value, transform: makeTemplateDeserializer( templates: templates, templateToType: templateToType, type: type ) ) } @inlinable func deserialize( _ value: Any, templates: [TemplateName: Any], templateToType: [TemplateName: String], validator: AnyArrayValueValidator? = nil, type: T.Type ) -> DeserializationResult<[T.ResolvedValue]> { deserialize( value, transform: makeTemplateDeserializer( templates: templates, templateToType: templateToType, type: type ), validator: validator ) } @usableFromInline func makeTemplateDeserializer( templates: [TemplateName: Any], templateToType: [TemplateName: String], type _: T.Type ) -> (([String: Any]) -> DeserializationResult) { { dict in let context = TemplatesContext( templates: templates, templateToType: templateToType, templateData: dict ) return T.resolveValue(context: context, useOnlyLinks: false) } }