Skip to content

Commit 854bed1

Browse files
committed
Add Decimal support
1 parent 70e69fb commit 854bed1

4 files changed

Lines changed: 22 additions & 60 deletions

File tree

Sources/MongoDBModel/AttributeValue.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ internal extension AttributeValue {
2525
self = .int64(value)
2626
case (.int64, .int32(let value)):
2727
self = .int64(numericCast(value))
28-
case (.boolean, .bool(let value)):
28+
case (.bool, .bool(let value)):
2929
self = .bool(value)
3030
case (.date, .datetime(let date)):
3131
self = .date(date)
@@ -57,6 +57,11 @@ internal extension AttributeValue {
5757
return nil
5858
}
5959
self = .url(url)
60+
case (.decimal, .decimal128(let decimal128)):
61+
guard let decimal = Decimal(string: decimal128.description) else {
62+
return nil
63+
}
64+
self = .decimal(decimal)
6065
case (_, .null):
6166
self = .null
6267
default:
@@ -67,18 +72,18 @@ internal extension AttributeValue {
6772

6873
public extension BSON {
6974

70-
init(attributeValue: AttributeValue) {
75+
init(attributeValue: AttributeValue) throws {
7176
switch attributeValue {
7277
case .null:
7378
self = .null
7479
case .string(let string):
7580
self = .string(string)
7681
case .uuid(let uuid):
77-
self = .binary(try! BSONBinary(from: uuid))
82+
self = .binary(try BSONBinary(from: uuid))
7883
case .url(let url):
7984
self = .string(url.absoluteString)
8085
case .data(let data):
81-
self = .binary(try! .init(data: data, subtype: .generic))
86+
self = .binary(try .init(data: data, subtype: .generic))
8287
case .date(let date):
8388
self = .datetime(date)
8489
case .bool(let value):
@@ -93,6 +98,9 @@ public extension BSON {
9398
self = .double(Double(float))
9499
case .double(let double):
95100
self = .double(double)
101+
case .decimal(let decimal):
102+
let bson = try BSONDecimal128(decimal.description)
103+
self = .decimal128(bson)
96104
}
97105
}
98106
}

Sources/MongoDBModel/ModelData.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,19 @@ public extension ModelData {
3535

3636
public extension BSONDocument {
3737

38-
init(model: ModelData) {
38+
init(model: ModelData) throws {
3939
self.init()
4040
// set id
4141
self[BSONDocument.BuiltInProperty.id.rawValue] = .string(model.id.rawValue)
4242
// set attributes
4343
for (key, attribute) in model.attributes {
44-
self[key.rawValue] = BSON(attributeValue: attribute)
44+
let attributeBSON: BSON
45+
do {
46+
attributeBSON = try BSON(attributeValue: attribute)
47+
} catch {
48+
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Unable to decode \(attribute) for \(key)", underlyingError: error))
49+
}
50+
self[key.rawValue] = attributeBSON
4551
}
4652
// set relationships
4753
for (key, relationship) in model.relationships {

Sources/MongoDBModel/MongoDatabase.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ internal extension MongoDatabase {
121121
) async throws {
122122
let entityName = value.entity
123123
let collection = self.collection(entityName, options: options)
124-
let document = BSONDocument(model: value)
124+
let document = try BSONDocument(model: value)
125125
try await collection.insertOne(document)
126126
}
127127

@@ -135,7 +135,7 @@ internal extension MongoDatabase {
135135
}
136136
for (entity, values) in collections {
137137
let collection = self.collection(entity, options: options[entity])
138-
let documents = values.map { BSONDocument(model: $0) }
138+
let documents = try values.map { try BSONDocument(model: $0) }
139139
try await collection.insertMany(documents)
140140
}
141141
}

Tests/CoreModelMongoDBTests/TestModel.swift

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -86,33 +86,6 @@ extension Person: Entity {
8686
)
8787
]
8888
}
89-
90-
init(from container: ModelData) throws {
91-
guard container.entity == Self.entityName else {
92-
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: Self.self)) from \(container.entity)"))
93-
}
94-
guard let id = UUID(uuidString: container.id.rawValue) else {
95-
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \(container.id)"))
96-
}
97-
self.id = id
98-
self.name = try container.decode(String.self, forKey: Person.CodingKeys.name)
99-
self.created = try container.decode(Date.self, forKey: Person.CodingKeys.created)
100-
self.age = try container.decode(UInt.self, forKey: Person.CodingKeys.age)
101-
self.events = try container.decodeRelationship([Event.ID].self, forKey: Person.CodingKeys.events)
102-
}
103-
104-
func encode() -> ModelData {
105-
106-
var container = ModelData(
107-
entity: Self.entityName,
108-
id: ObjectID(rawValue: self.id.description)
109-
)
110-
container.encode(self.name, forKey: Person.CodingKeys.name)
111-
container.encode(self.created, forKey: Person.CodingKeys.created)
112-
container.encode(self.age, forKey: Person.CodingKeys.age)
113-
container.encodeRelationship(self.events, forKey: Person.CodingKeys.events)
114-
return container
115-
}
11689
}
11790

11891
struct Event: Equatable, Hashable, Codable, Identifiable {
@@ -183,29 +156,4 @@ extension Event: Entity {
183156
inverseRelationship: PropertyKey(Person.CodingKeys.events))
184157
]
185158
}
186-
187-
init(from container: ModelData) throws {
188-
guard container.entity == Self.entityName else {
189-
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: Self.self)) from \(container.entity)"))
190-
}
191-
guard let id = UUID(uuidString: container.id.rawValue) else {
192-
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \(container.id)"))
193-
}
194-
self.id = id
195-
self.name = try container.decode(String.self, forKey: Event.CodingKeys.name)
196-
self.date = try container.decode(Date.self, forKey: Event.CodingKeys.date)
197-
self.people = try container.decodeRelationship([Person.ID].self, forKey: Event.CodingKeys.people)
198-
}
199-
200-
func encode() -> ModelData {
201-
202-
var container = ModelData(
203-
entity: Self.entityName,
204-
id: ObjectID(rawValue: self.id.description)
205-
)
206-
container.encode(self.name, forKey: Event.CodingKeys.name)
207-
container.encode(self.date, forKey: Event.CodingKeys.date)
208-
container.encodeRelationship(self.people, forKey: Event.CodingKeys.people)
209-
return container
210-
}
211159
}

0 commit comments

Comments
 (0)