Skip to content

Commit 81048e4

Browse files
authored
Merge pull request #1192 from bubski/codable-measurement-2
Codable conformance for Measurement
2 parents aea30ad + 9dcfe9d commit 81048e4

File tree

7 files changed

+522
-120
lines changed

7 files changed

+522
-120
lines changed

Foundation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
231503DB1D8AEE5D0061694D /* TestDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestDecimal.swift */; };
1515
294E3C1D1CC5E19300E4F44C /* TestNSAttributedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */; };
1616
2EBE67A51C77BF0E006583D5 /* TestDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */; };
17+
3E55A2331F52463B00082000 /* TestUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E55A2321F52463B00082000 /* TestUnit.swift */; };
1718
3EA9D6701EF0532D00B362D6 /* TestJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */; };
1819
3EDCE50C1EF04D8100C2EC04 /* Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5051EF04D8100C2EC04 /* Codable.swift */; };
1920
3EDCE5101EF04D8100C2EC04 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */; };
@@ -490,6 +491,7 @@
490491
231503DA1D8AEE5D0061694D /* TestDecimal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDecimal.swift; sourceTree = "<group>"; };
491492
294E3C1C1CC5E19300E4F44C /* TestNSAttributedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSAttributedString.swift; sourceTree = "<group>"; };
492493
2EBE67A31C77BF05006583D5 /* TestDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDateFormatter.swift; sourceTree = "<group>"; };
494+
3E55A2321F52463B00082000 /* TestUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUnit.swift; sourceTree = "<group>"; };
493495
3EA9D66F1EF0532D00B362D6 /* TestJSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestJSONEncoder.swift; sourceTree = "<group>"; };
494496
3EDCE5051EF04D8100C2EC04 /* Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Codable.swift; sourceTree = "<group>"; };
495497
3EDCE5091EF04D8100C2EC04 /* JSONEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONEncoder.swift; sourceTree = "<group>"; };
@@ -1494,6 +1496,7 @@
14941496
D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
14951497
5B6F17961C48631C00935030 /* TestUtils.swift */,
14961498
03B6F5831F15F339004F25AF /* TestURLProtocol.swift */,
1499+
3E55A2321F52463B00082000 /* TestUnit.swift */,
14971500
);
14981501
name = Tests;
14991502
sourceTree = "<group>";
@@ -2419,6 +2422,7 @@
24192422
F9E0BB371CA70B8000F7FF3C /* TestURLCredential.swift in Sources */,
24202423
5B13B3341C582D4C00651CE2 /* TestNSKeyedArchiver.swift in Sources */,
24212424
5B13B3441C582D4C00651CE2 /* TestNSSet.swift in Sources */,
2425+
3E55A2331F52463B00082000 /* TestUnit.swift in Sources */,
24222426
5B13B3321C582D4C00651CE2 /* TestIndexSet.swift in Sources */,
24232427
5B13B3511C582D4C00651CE2 /* TestByteCountFormatter.swift in Sources */,
24242428
BDFDF0A71DFF5B3E00C04CC5 /* TestPersonNameComponents.swift in Sources */,

Foundation/Measurement.swift

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,60 @@ extension Measurement : _ObjectTypeBridgeable {
275275
return Measurement(value: source!.doubleValue, unit: u)
276276
}
277277
}
278+
279+
extension Measurement : Codable {
280+
private enum CodingKeys : Int, CodingKey {
281+
case value
282+
case unit
283+
}
284+
285+
private enum UnitCodingKeys : Int, CodingKey {
286+
case symbol
287+
case converter
288+
}
289+
290+
private enum LinearConverterCodingKeys : Int, CodingKey {
291+
case coefficient
292+
case constant
293+
}
294+
295+
public init(from decoder: Decoder) throws {
296+
let container = try decoder.container(keyedBy: CodingKeys.self)
297+
let value = try container.decode(Double.self, forKey: .value)
298+
299+
let unitContainer = try container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
300+
let symbol = try unitContainer.decode(String.self, forKey: .symbol)
301+
302+
let unit: UnitType
303+
if UnitType.self is Dimension.Type {
304+
let converterContainer = try unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
305+
let coefficient = try converterContainer.decode(Double.self, forKey: .coefficient)
306+
let constant = try converterContainer.decode(Double.self, forKey: .constant)
307+
let unitMetaType = (UnitType.self as! Dimension.Type)
308+
unit = (unitMetaType.init(symbol: symbol, converter: UnitConverterLinear(coefficient: coefficient, constant: constant)) as! UnitType)
309+
} else {
310+
unit = UnitType(symbol: symbol)
311+
}
312+
313+
self.init(value: value, unit: unit)
314+
}
315+
316+
public func encode(to encoder: Encoder) throws {
317+
var container = encoder.container(keyedBy: CodingKeys.self)
318+
try container.encode(self.value, forKey: .value)
319+
320+
var unitContainer = container.nestedContainer(keyedBy: UnitCodingKeys.self, forKey: .unit)
321+
try unitContainer.encode(self.unit.symbol, forKey: .symbol)
322+
323+
if UnitType.self is Dimension.Type {
324+
guard type(of: (self.unit as! Dimension).converter) is UnitConverterLinear.Type else {
325+
preconditionFailure("Cannot encode a Measurement whose UnitType has a non-linear unit converter.")
326+
}
327+
328+
let converter = (self.unit as! Dimension).converter as! UnitConverterLinear
329+
var converterContainer = unitContainer.nestedContainer(keyedBy: LinearConverterCodingKeys.self, forKey: .converter)
330+
try converterContainer.encode(converter.coefficient, forKey: .coefficient)
331+
try converterContainer.encode(converter.constant, forKey: .constant)
332+
}
333+
}
334+
}

0 commit comments

Comments
 (0)