From f5d9d1d5921ec88725c89b5990bd65072166efa8 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sat, 19 Aug 2023 05:28:04 -0400 Subject: [PATCH 1/2] Add `Decimal` support #8 --- Sources/CoreDataModel/NSAttributeType.swift | 4 +++- Sources/CoreDataModel/NSManagedObject.swift | 4 ++++ Sources/CoreModel/AttributeType.swift | 3 +++ Sources/CoreModel/Decodable.swift | 10 ++++++++++ Sources/CoreModel/PropertyValue.swift | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Sources/CoreDataModel/NSAttributeType.swift b/Sources/CoreDataModel/NSAttributeType.swift index 62e5bc4..18aa52d 100644 --- a/Sources/CoreDataModel/NSAttributeType.swift +++ b/Sources/CoreDataModel/NSAttributeType.swift @@ -36,6 +36,8 @@ public extension NSAttributeType { self = .UUIDAttributeType case .url: self = .URIAttributeType + case .decimal: + self = .decimalAttributeType } } } @@ -53,7 +55,7 @@ public extension AttributeType { case .integer64AttributeType: self = .int64 case .decimalAttributeType: - return nil + self = .decimal case .doubleAttributeType: self = .double case .floatAttributeType: diff --git a/Sources/CoreDataModel/NSManagedObject.swift b/Sources/CoreDataModel/NSManagedObject.swift index 7e67061..f549820 100644 --- a/Sources/CoreDataModel/NSManagedObject.swift +++ b/Sources/CoreDataModel/NSManagedObject.swift @@ -47,6 +47,8 @@ internal extension NSManagedObject { return .float(value) } else if let value = objectValue as? Double { return .double(value) + } else if let value = objectValue as? NSDecimalNumber { + return .decimal(value as Decimal) } else { assertionFailure("Invalid CoreData attribute value \(objectValue)") throw CocoaError(.coreData) @@ -82,6 +84,8 @@ internal extension NSManagedObject { objectValue = value as NSNumber case let .double(value): objectValue = value as NSNumber + case let .decimal(value): + objectValue = value as NSDecimalNumber } self.setValue(objectValue, forKey: key.rawValue) diff --git a/Sources/CoreModel/AttributeType.swift b/Sources/CoreModel/AttributeType.swift index bcfaf1d..6ee7f20 100644 --- a/Sources/CoreModel/AttributeType.swift +++ b/Sources/CoreModel/AttributeType.swift @@ -42,4 +42,7 @@ public enum AttributeType: String, Codable, CaseIterable, Sendable { /// URL case url + + /// Decimal + case decimal } diff --git a/Sources/CoreModel/Decodable.swift b/Sources/CoreModel/Decodable.swift index f2b89ee..471a003 100644 --- a/Sources/CoreModel/Decodable.swift +++ b/Sources/CoreModel/Decodable.swift @@ -192,6 +192,7 @@ extension Int: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -216,6 +217,7 @@ extension Int8: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -240,6 +242,7 @@ extension Int16: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -264,6 +267,7 @@ extension Int32: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -288,6 +292,7 @@ extension Int64: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -312,6 +317,7 @@ extension UInt: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -337,6 +343,7 @@ extension UInt8: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -362,6 +369,7 @@ extension UInt16: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -387,6 +395,7 @@ extension UInt32: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil @@ -411,6 +420,7 @@ extension UInt64: AttributeDecodable { .data, .date, .bool, + .decimal, .float, .double: return nil diff --git a/Sources/CoreModel/PropertyValue.swift b/Sources/CoreModel/PropertyValue.swift index d1db2e9..e3c4434 100644 --- a/Sources/CoreModel/PropertyValue.swift +++ b/Sources/CoreModel/PropertyValue.swift @@ -22,6 +22,7 @@ public enum AttributeValue: Equatable, Hashable, Codable { case int64(Int64) case float(Float) case double(Double) + case decimal(Decimal) } /// CoreModel Relationship Value From b85eabf05407ad8b76290de009677d0cb96b02b2 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sat, 19 Aug 2023 05:33:43 -0400 Subject: [PATCH 2/2] Add `AttributeCodable` support for Decimal --- Sources/CoreModel/Decodable.swift | 10 ++++++++++ Sources/CoreModel/Decoder.swift | 8 -------- Sources/CoreModel/Encodable.swift | 5 +++++ Sources/CoreModel/Encoder.swift | 10 +--------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Sources/CoreModel/Decodable.swift b/Sources/CoreModel/Decodable.swift index 471a003..202abeb 100644 --- a/Sources/CoreModel/Decodable.swift +++ b/Sources/CoreModel/Decodable.swift @@ -161,6 +161,16 @@ extension Data: AttributeDecodable { } } +extension Decimal: AttributeDecodable { + + public init?(attributeValue: AttributeValue) { + guard case let .decimal(value) = attributeValue else { + return nil + } + self = value + } +} + extension Float: AttributeDecodable { public init?(attributeValue: AttributeValue) { diff --git a/Sources/CoreModel/Decoder.swift b/Sources/CoreModel/Decoder.swift index 8002cee..dd86d99 100644 --- a/Sources/CoreModel/Decoder.swift +++ b/Sources/CoreModel/Decoder.swift @@ -192,14 +192,6 @@ internal extension ModelDataDecoder { throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode \(type) from identifier \(id)")) } return value as! T - } else if type == Data.self { - return try decodeAttribute(Data.self, forKey: key) as! T - } else if type == Date.self { - return try decodeAttribute(Date.self, forKey: key) as! T - } else if type == UUID.self { - return try decodeAttribute(UUID.self, forKey: key) as! T - } else if type == URL.self { - return try decodeAttribute(URL.self, forKey: key) as! T } else if let decodableType = type as? AttributeDecodable.Type { return try decodeAttribute(decodableType, forKey: key) as! T } else { diff --git a/Sources/CoreModel/Encodable.swift b/Sources/CoreModel/Encodable.swift index a1c97a4..e4b11fb 100644 --- a/Sources/CoreModel/Encodable.swift +++ b/Sources/CoreModel/Encodable.swift @@ -147,3 +147,8 @@ extension URL: AttributeEncodable { public var attributeValue: AttributeValue { .url(self) } } + +extension Decimal: AttributeEncodable { + + public var attributeValue: AttributeValue { .decimal(self) } +} diff --git a/Sources/CoreModel/Encoder.swift b/Sources/CoreModel/Encoder.swift index 07b39a0..a6c7ada 100644 --- a/Sources/CoreModel/Encoder.swift +++ b/Sources/CoreModel/Encoder.swift @@ -123,15 +123,7 @@ internal extension ModelDataEncoder { func setEncodable (_ value: T, forKey key: PropertyKey) throws { - if let data = value as? Data { - try setAttribute(data.attributeValue, forKey: key) - } else if let date = value as? Date { - try setAttribute(date.attributeValue, forKey: key) - } else if let uuid = value as? UUID { - try setAttribute(uuid.attributeValue, forKey: key) - } else if let url = value as? URL { - try setAttribute(url.attributeValue, forKey: key) - } else if let encodable = value as? AttributeEncodable { + if let encodable = value as? AttributeEncodable { try setAttribute(encodable.attributeValue, forKey: key) } else { // encode using Encodable, container should write directly.