Skip to content

Commit

Permalink
Add Decimal support
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Aug 19, 2023
1 parent 70e69fb commit 854bed1
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 60 deletions.
16 changes: 12 additions & 4 deletions Sources/MongoDBModel/AttributeValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal extension AttributeValue {
self = .int64(value)
case (.int64, .int32(let value)):
self = .int64(numericCast(value))
case (.boolean, .bool(let value)):
case (.bool, .bool(let value)):
self = .bool(value)
case (.date, .datetime(let date)):
self = .date(date)
Expand Down Expand Up @@ -57,6 +57,11 @@ internal extension AttributeValue {
return nil
}
self = .url(url)
case (.decimal, .decimal128(let decimal128)):
guard let decimal = Decimal(string: decimal128.description) else {
return nil
}
self = .decimal(decimal)
case (_, .null):
self = .null
default:
Expand All @@ -67,18 +72,18 @@ internal extension AttributeValue {

public extension BSON {

init(attributeValue: AttributeValue) {
init(attributeValue: AttributeValue) throws {
switch attributeValue {
case .null:
self = .null
case .string(let string):
self = .string(string)
case .uuid(let uuid):
self = .binary(try! BSONBinary(from: uuid))
self = .binary(try BSONBinary(from: uuid))
case .url(let url):
self = .string(url.absoluteString)
case .data(let data):
self = .binary(try! .init(data: data, subtype: .generic))
self = .binary(try .init(data: data, subtype: .generic))
case .date(let date):
self = .datetime(date)
case .bool(let value):
Expand All @@ -93,6 +98,9 @@ public extension BSON {
self = .double(Double(float))
case .double(let double):
self = .double(double)
case .decimal(let decimal):
let bson = try BSONDecimal128(decimal.description)
self = .decimal128(bson)
}
}
}
10 changes: 8 additions & 2 deletions Sources/MongoDBModel/ModelData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ public extension ModelData {

public extension BSONDocument {

init(model: ModelData) {
init(model: ModelData) throws {
self.init()
// set id
self[BSONDocument.BuiltInProperty.id.rawValue] = .string(model.id.rawValue)
// set attributes
for (key, attribute) in model.attributes {
self[key.rawValue] = BSON(attributeValue: attribute)
let attributeBSON: BSON
do {
attributeBSON = try BSON(attributeValue: attribute)
} catch {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Unable to decode \(attribute) for \(key)", underlyingError: error))
}
self[key.rawValue] = attributeBSON
}
// set relationships
for (key, relationship) in model.relationships {
Expand Down
4 changes: 2 additions & 2 deletions Sources/MongoDBModel/MongoDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ internal extension MongoDatabase {
) async throws {
let entityName = value.entity
let collection = self.collection(entityName, options: options)
let document = BSONDocument(model: value)
let document = try BSONDocument(model: value)
try await collection.insertOne(document)
}

Expand All @@ -135,7 +135,7 @@ internal extension MongoDatabase {
}
for (entity, values) in collections {
let collection = self.collection(entity, options: options[entity])
let documents = values.map { BSONDocument(model: $0) }
let documents = try values.map { try BSONDocument(model: $0) }
try await collection.insertMany(documents)
}
}
Expand Down
52 changes: 0 additions & 52 deletions Tests/CoreModelMongoDBTests/TestModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,33 +86,6 @@ extension Person: Entity {
)
]
}

init(from container: ModelData) throws {
guard container.entity == Self.entityName else {
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: Self.self)) from \(container.entity)"))
}
guard let id = UUID(uuidString: container.id.rawValue) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \(container.id)"))
}
self.id = id
self.name = try container.decode(String.self, forKey: Person.CodingKeys.name)
self.created = try container.decode(Date.self, forKey: Person.CodingKeys.created)
self.age = try container.decode(UInt.self, forKey: Person.CodingKeys.age)
self.events = try container.decodeRelationship([Event.ID].self, forKey: Person.CodingKeys.events)
}

func encode() -> ModelData {

var container = ModelData(
entity: Self.entityName,
id: ObjectID(rawValue: self.id.description)
)
container.encode(self.name, forKey: Person.CodingKeys.name)
container.encode(self.created, forKey: Person.CodingKeys.created)
container.encode(self.age, forKey: Person.CodingKeys.age)
container.encodeRelationship(self.events, forKey: Person.CodingKeys.events)
return container
}
}

struct Event: Equatable, Hashable, Codable, Identifiable {
Expand Down Expand Up @@ -183,29 +156,4 @@ extension Event: Entity {
inverseRelationship: PropertyKey(Person.CodingKeys.events))
]
}

init(from container: ModelData) throws {
guard container.entity == Self.entityName else {
throw DecodingError.typeMismatch(Self.self, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: Self.self)) from \(container.entity)"))
}
guard let id = UUID(uuidString: container.id.rawValue) else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \(container.id)"))
}
self.id = id
self.name = try container.decode(String.self, forKey: Event.CodingKeys.name)
self.date = try container.decode(Date.self, forKey: Event.CodingKeys.date)
self.people = try container.decodeRelationship([Person.ID].self, forKey: Event.CodingKeys.people)
}

func encode() -> ModelData {

var container = ModelData(
entity: Self.entityName,
id: ObjectID(rawValue: self.id.description)
)
container.encode(self.name, forKey: Event.CodingKeys.name)
container.encode(self.date, forKey: Event.CodingKeys.date)
container.encodeRelationship(self.people, forKey: Event.CodingKeys.people)
return container
}
}

0 comments on commit 854bed1

Please sign in to comment.