Skip to content

Commit 1a6d322

Browse files
committed
Add ModelUnkeyedEncodingContainer
1 parent bd838fc commit 1a6d322

1 file changed

Lines changed: 155 additions & 5 deletions

File tree

Sources/CoreModel/Encoder.swift

Lines changed: 155 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,19 @@ internal final class ModelDataEncoder: Encoder {
5555
self.userInfo = userInfo
5656
self.log = log
5757
self.data = ModelData(entity: entity.id, id: id)
58-
self.attributes = .init(grouping: entity.attributes, by: { $0.id.rawValue })
59-
self.relationships = .init(grouping: entity.relationships, by: { $0.id.rawValue })
58+
// properties cache
59+
var attributes = [PropertyKey: Attribute]()
60+
attributes.reserveCapacity(entity.attributes.count)
61+
for attribute in entity.attributes {
62+
attributes[attribute.id] = attribute
63+
}
64+
self.attributes = attributes //.init(grouping: entity.attributes, by: { $0.id })
65+
var relationships = [PropertyKey: Relationship]()
66+
relationships.reserveCapacity(entity.relationships.count)
67+
for relationship in entity.relationships {
68+
relationships[relationship.id] = relationship
69+
}
70+
self.relationships = relationships //.init(grouping: entity.relationships, by: { $0.id })
6071
}
6172

6273
func container<Key>(keyedBy type: Key.Type) -> Swift.KeyedEncodingContainer<Key> where Key : CodingKey {
@@ -67,13 +78,13 @@ internal final class ModelDataEncoder: Encoder {
6778

6879
func unkeyedContainer() -> Swift.UnkeyedEncodingContainer {
6980
log?("Requested unkeyed container for path \"\(codingPath.path)\"")
70-
return ModelUnkeyedEncodingContainer(encoder: self)
81+
return ModelUnkeyedEncodingContainer(referencing: self)
7182
}
7283

7384
func singleValueContainer() -> Swift.SingleValueEncodingContainer {
7485
log?("Requested single value container for path \"\(codingPath.path)\"")
7586
assert(self.codingPath.last != nil)
76-
return ModelSingleValueEncodingContainer(encoder: self)
87+
return ModelSingleValueEncodingContainer(referencing: self)
7788
}
7889
}
7990

@@ -272,7 +283,7 @@ struct ModelKeyedEncodingContainer<K : CodingKey> : KeyedEncodingContainerProtoc
272283

273284
// MARK: - SingleValueEncodingContainer
274285

275-
internal final class ModelSingleValueEncodingContainer: SingleValueEncodingContainer {
286+
struct ModelSingleValueEncodingContainer: SingleValueEncodingContainer {
276287

277288
// MARK: Properties
278289

@@ -372,3 +383,142 @@ internal final class ModelSingleValueEncodingContainer: SingleValueEncodingConta
372383
try encoder.setAttribute(value.attributeValue, forKey: key)
373384
}
374385
}
386+
387+
388+
// MARK: - UnkeyedEncodingContainer
389+
390+
internal final class ModelUnkeyedEncodingContainer: UnkeyedEncodingContainer {
391+
392+
// MARK: Properties
393+
394+
/// A reference to the encoder we're writing to.
395+
let encoder: ModelDataEncoder
396+
397+
/// The path of coding keys taken to get to this point in encoding.
398+
let codingPath: [CodingKey]
399+
400+
private var objectIDs = [ObjectID]()
401+
402+
// MARK: Initialization
403+
404+
init(referencing encoder: ModelDataEncoder) {
405+
self.encoder = encoder
406+
self.codingPath = encoder.codingPath
407+
}
408+
409+
deinit {
410+
writeArray()
411+
}
412+
413+
// MARK: - Methods
414+
415+
var count: Int {
416+
objectIDs.count
417+
}
418+
419+
func encodeNil() throws {
420+
throw EncodingError.invalidValue(type(of: Optional<Any>.self), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(Optional<Any>.self)"))
421+
}
422+
423+
func encode(_ value: String) throws {
424+
try encodeRelationship(value)
425+
}
426+
427+
func encode(_ value: Bool) throws {
428+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
429+
}
430+
431+
func encode(_ value: Double) throws {
432+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
433+
}
434+
435+
func encode(_ value: Float) throws {
436+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
437+
}
438+
439+
func encode(_ value: Int) throws {
440+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
441+
}
442+
443+
func encode(_ value: Int8) throws {
444+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
445+
}
446+
447+
func encode(_ value: Int16) throws {
448+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
449+
}
450+
451+
func encode(_ value: Int32) throws {
452+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
453+
}
454+
455+
func encode(_ value: Int64) throws {
456+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
457+
}
458+
459+
func encode(_ value: UInt) throws {
460+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
461+
}
462+
463+
func encode(_ value: UInt8) throws {
464+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
465+
}
466+
467+
func encode(_ value: UInt16) throws {
468+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
469+
}
470+
471+
func encode(_ value: UInt32) throws {
472+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
473+
}
474+
475+
func encode(_ value: UInt64) throws {
476+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
477+
}
478+
479+
func encode <T: Encodable> (_ value: T) throws {
480+
guard let stringConvertible = value as? CustomStringConvertible else {
481+
throw EncodingError.invalidValue(type(of: value), EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode to-many relationship of \(type(of: value))"))
482+
}
483+
let string = stringConvertible.description
484+
try encodeRelationship(string)
485+
}
486+
487+
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
488+
fatalError()
489+
}
490+
491+
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
492+
fatalError()
493+
}
494+
495+
func superEncoder() -> Encoder {
496+
encoder
497+
}
498+
499+
// MARK: Private Methods
500+
501+
private func propertyKey() throws -> PropertyKey {
502+
guard let key = codingPath.first else {
503+
throw EncodingError.invalidValue(Any.self, EncodingError.Context(codingPath: codingPath, debugDescription: "Invalid coding path"))
504+
}
505+
return PropertyKey(key)
506+
}
507+
508+
private func encodeRelationship(_ string: String) throws {
509+
objectIDs.append(ObjectID(rawValue: string))
510+
}
511+
512+
private func writeArray() {
513+
// set key to be written
514+
guard let codingKey = codingPath.first else {
515+
//throw EncodingError.invalidValue(Any.self, EncodingError.Context(codingPath: codingPath, debugDescription: "Invalid coding path"))
516+
return
517+
}
518+
let key = PropertyKey(codingKey)
519+
// write final value
520+
let value = RelationshipValue.toMany(objectIDs)
521+
encoder.log?("Will set \(value) for relationship \"\(key)\"")
522+
encoder.data.relationships[key] = value
523+
}
524+
}

0 commit comments

Comments
 (0)