Skip to content

Commit 35e1a69

Browse files
committed
Add ModelData.decode()
1 parent 8784c6f commit 35e1a69

1 file changed

Lines changed: 391 additions & 0 deletions

File tree

Sources/CoreModel/Decodable.swift

Lines changed: 391 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,391 @@
1+
//
2+
// Decodable.swift
3+
//
4+
//
5+
// Created by Alsey Coleman Miller on 8/17/23.
6+
//
7+
8+
import Foundation
9+
10+
public extension ModelData {
11+
12+
func decode<T, K>(_ type: T.Type, forKey key: K) throws -> T where T: AttributeDecodable, K: CodingKey {
13+
14+
let property = PropertyKey(key)
15+
guard let attribute = self.attributes[property] else {
16+
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: [], debugDescription: "Key \(key.stringValue) not found"))
17+
}
18+
// TODO: Optional values
19+
/*
20+
guard attribute != .null else {
21+
return
22+
}*/
23+
guard let decodable = type.init(attributeValue: attribute) else {
24+
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: type)) from \(attribute)"))
25+
}
26+
return decodable
27+
}
28+
29+
func decodeRelationship<T, K>(_ type: T.Type, forKey key: K) throws -> T where T: ObjectIDConvertible, K: CodingKey {
30+
31+
let property = PropertyKey(key)
32+
guard let relationship = self.relationships[property] else {
33+
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: [], debugDescription: "Key \(key.stringValue) not found"))
34+
}
35+
switch relationship {
36+
case .null:
37+
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: [], debugDescription: "Key \(key.stringValue) not found"))
38+
case .toMany:
39+
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: type)) from \(relationship)"))
40+
case let .toOne(objectID):
41+
guard let id = type.init(objectID: objectID) else {
42+
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \(objectID)"))
43+
}
44+
return id
45+
}
46+
}
47+
48+
func decodeRelationship<T, K>(_ type: [T].Type, forKey key: K) throws -> [T] where T: ObjectIDConvertible, K: CodingKey {
49+
50+
let property = PropertyKey(key)
51+
guard let relationship = self.relationships[property] else {
52+
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: [], debugDescription: "Key \(key.stringValue) not found"))
53+
}
54+
switch relationship {
55+
case .null:
56+
return []
57+
case .toOne:
58+
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: [], debugDescription: "Cannot decode \(String(describing: type)) from \(relationship)"))
59+
case let .toMany(objectIDs):
60+
return try objectIDs.map {
61+
guard let id = T.init(objectID: $0) else {
62+
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Cannot decode identifier from \($0)"))
63+
}
64+
return id
65+
}
66+
}
67+
}
68+
}
69+
70+
extension Entity where Self: Decodable, Self.ID: Decodable {
71+
72+
// TODO: Default implementation for Decodable
73+
}
74+
75+
public protocol AttributeDecodable {
76+
77+
init?(attributeValue: AttributeValue)
78+
}
79+
80+
extension String: AttributeDecodable {
81+
82+
public init?(attributeValue: AttributeValue) {
83+
guard case let .string(value) = attributeValue else {
84+
return nil
85+
}
86+
self = value
87+
}
88+
}
89+
90+
extension UUID: AttributeDecodable {
91+
92+
public init?(attributeValue: AttributeValue) {
93+
guard case let .uuid(value) = attributeValue else {
94+
return nil
95+
}
96+
self = value
97+
}
98+
}
99+
100+
extension URL: AttributeDecodable {
101+
102+
public init?(attributeValue: AttributeValue) {
103+
guard case let .url(value) = attributeValue else {
104+
return nil
105+
}
106+
self = value
107+
}
108+
}
109+
110+
extension Date: AttributeDecodable {
111+
112+
public init?(attributeValue: AttributeValue) {
113+
guard case let .date(value) = attributeValue else {
114+
return nil
115+
}
116+
self = value
117+
}
118+
}
119+
120+
extension Data: AttributeDecodable {
121+
122+
public init?(attributeValue: AttributeValue) {
123+
guard case let .data(value) = attributeValue else {
124+
return nil
125+
}
126+
self = value
127+
}
128+
}
129+
130+
extension Float: AttributeDecodable {
131+
132+
public init?(attributeValue: AttributeValue) {
133+
guard case let .float(value) = attributeValue else {
134+
return nil
135+
}
136+
self = value
137+
}
138+
}
139+
140+
extension Double: AttributeDecodable {
141+
142+
public init?(attributeValue: AttributeValue) {
143+
guard case let .double(value) = attributeValue else {
144+
return nil
145+
}
146+
self = value
147+
}
148+
}
149+
150+
extension Int: AttributeDecodable {
151+
152+
public init?(attributeValue: AttributeValue) {
153+
switch attributeValue {
154+
case .null,
155+
.string,
156+
.uuid,
157+
.url,
158+
.data,
159+
.date,
160+
.bool,
161+
.float,
162+
.double:
163+
return nil
164+
case let .int16(value):
165+
self = numericCast(value)
166+
case let .int32(value):
167+
self = numericCast(value)
168+
case let .int64(value):
169+
self = numericCast(value)
170+
}
171+
}
172+
}
173+
174+
extension Int8: AttributeDecodable {
175+
176+
public init?(attributeValue: AttributeValue) {
177+
switch attributeValue {
178+
case .null,
179+
.string,
180+
.uuid,
181+
.url,
182+
.data,
183+
.date,
184+
.bool,
185+
.float,
186+
.double:
187+
return nil
188+
case let .int16(value):
189+
self = numericCast(value)
190+
case let .int32(value):
191+
self = numericCast(value)
192+
case let .int64(value):
193+
self = numericCast(value)
194+
}
195+
}
196+
}
197+
198+
extension Int16: AttributeDecodable {
199+
200+
public init?(attributeValue: AttributeValue) {
201+
switch attributeValue {
202+
case .null,
203+
.string,
204+
.uuid,
205+
.url,
206+
.data,
207+
.date,
208+
.bool,
209+
.float,
210+
.double:
211+
return nil
212+
case let .int16(value):
213+
self = value
214+
case let .int32(value):
215+
self = numericCast(value)
216+
case let .int64(value):
217+
self = numericCast(value)
218+
}
219+
}
220+
}
221+
222+
extension Int32: AttributeDecodable {
223+
224+
public init?(attributeValue: AttributeValue) {
225+
switch attributeValue {
226+
case .null,
227+
.string,
228+
.uuid,
229+
.url,
230+
.data,
231+
.date,
232+
.bool,
233+
.float,
234+
.double:
235+
return nil
236+
case let .int16(value):
237+
self = numericCast(value)
238+
case let .int32(value):
239+
self = value
240+
case let .int64(value):
241+
self = numericCast(value)
242+
}
243+
}
244+
}
245+
246+
extension Int64: AttributeDecodable {
247+
248+
public init?(attributeValue: AttributeValue) {
249+
switch attributeValue {
250+
case .null,
251+
.string,
252+
.uuid,
253+
.url,
254+
.data,
255+
.date,
256+
.bool,
257+
.float,
258+
.double:
259+
return nil
260+
case let .int16(value):
261+
self = numericCast(value)
262+
case let .int32(value):
263+
self = numericCast(value)
264+
case let .int64(value):
265+
self = value
266+
}
267+
}
268+
}
269+
270+
extension UInt: AttributeDecodable {
271+
272+
public init?(attributeValue: AttributeValue) {
273+
switch attributeValue {
274+
case .null,
275+
.string,
276+
.uuid,
277+
.url,
278+
.data,
279+
.date,
280+
.bool,
281+
.float,
282+
.double:
283+
return nil
284+
case let .int16(value):
285+
self = numericCast(value)
286+
case let .int32(value):
287+
self = numericCast(value)
288+
case let .int64(value):
289+
self = numericCast(value)
290+
}
291+
}
292+
}
293+
294+
295+
extension UInt8: AttributeDecodable {
296+
297+
public init?(attributeValue: AttributeValue) {
298+
switch attributeValue {
299+
case .null,
300+
.string,
301+
.uuid,
302+
.url,
303+
.data,
304+
.date,
305+
.bool,
306+
.float,
307+
.double:
308+
return nil
309+
case let .int16(value):
310+
self = numericCast(value)
311+
case let .int32(value):
312+
self = numericCast(value)
313+
case let .int64(value):
314+
self = numericCast(value)
315+
}
316+
}
317+
}
318+
319+
320+
extension UInt16: AttributeDecodable {
321+
322+
public init?(attributeValue: AttributeValue) {
323+
switch attributeValue {
324+
case .null,
325+
.string,
326+
.uuid,
327+
.url,
328+
.data,
329+
.date,
330+
.bool,
331+
.float,
332+
.double:
333+
return nil
334+
case let .int16(value):
335+
self = numericCast(value)
336+
case let .int32(value):
337+
self = numericCast(value)
338+
case let .int64(value):
339+
self = numericCast(value)
340+
}
341+
}
342+
}
343+
344+
345+
extension UInt32: AttributeDecodable {
346+
347+
public init?(attributeValue: AttributeValue) {
348+
switch attributeValue {
349+
case .null,
350+
.string,
351+
.uuid,
352+
.url,
353+
.data,
354+
.date,
355+
.bool,
356+
.float,
357+
.double:
358+
return nil
359+
case let .int16(value):
360+
self = numericCast(value)
361+
case let .int32(value):
362+
self = numericCast(value)
363+
case let .int64(value):
364+
self = numericCast(value)
365+
}
366+
}
367+
}
368+
369+
extension UInt64: AttributeDecodable {
370+
371+
public init?(attributeValue: AttributeValue) {
372+
switch attributeValue {
373+
case .null,
374+
.string,
375+
.uuid,
376+
.url,
377+
.data,
378+
.date,
379+
.bool,
380+
.float,
381+
.double:
382+
return nil
383+
case let .int16(value):
384+
self = numericCast(value)
385+
case let .int32(value):
386+
self = numericCast(value)
387+
case let .int64(value):
388+
self = numericCast(value)
389+
}
390+
}
391+
}

0 commit comments

Comments
 (0)