Skip to content

Commit c45cdb7

Browse files
committed
Added Codable conformance for Range, ClosedRange, PartialRangeUpTo, PartialRangeThrough and PartialRangeFrom
1 parent c7adca2 commit c45cdb7

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

stdlib/public/core/ClosedRange.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,28 @@ extension ClosedRange {
488488
// shorthand. TODO: Add documentation
489489
public typealias CountableClosedRange<Bound: Strideable> = ClosedRange<Bound>
490490
where Bound.Stride : SignedInteger
491+
492+
extension ClosedRange: Codable where Bound: Codable {
493+
private enum CodingKeys: String, CodingKey {
494+
case from
495+
case to
496+
}
497+
498+
@inlinable
499+
public init(from decoder: Decoder) throws {
500+
let container = try decoder.container(keyedBy: CodingKeys.self)
501+
let lowerBound = try container.decode(Bound.self, forKey: .from)
502+
let upperBound = try container.decode(Bound.self, forKey: .to)
503+
guard lowerBound <= upperBound else {
504+
throw DecodingError.dataCorruptedError(forKey: CodingKeys.to, in: container, debugDescription: "upperBound (to) cannot be lower than lowerBound (from)")
505+
}
506+
self = lowerBound...upperBound
507+
}
508+
509+
@inlinable
510+
public func encode(to encoder: Encoder) throws {
511+
var container = encoder.container(keyedBy: CodingKeys.self)
512+
try container.encode(self.lowerBound, forKey: .from)
513+
try container.encode(self.upperBound, forKey: .to)
514+
}
515+
}

stdlib/public/core/Range.swift

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,31 @@ extension Range: Hashable where Bound: Hashable {
405405
}
406406
}
407407

408+
extension Range: Codable where Bound: Codable {
409+
private enum CodingKeys: String, CodingKey {
410+
case from
411+
case upTo
412+
}
413+
414+
@inlinable
415+
public init(from decoder: Decoder) throws {
416+
let container = try decoder.container(keyedBy: CodingKeys.self)
417+
let lowerBound = try container.decode(Bound.self, forKey: .from)
418+
let upperBound = try container.decode(Bound.self, forKey: .upTo)
419+
guard lowerBound <= upperBound else {
420+
throw DecodingError.dataCorruptedError(forKey: CodingKeys.upTo, in: container, debugDescription: "upperBound (upTo) cannot be lower than lowerBound (from)")
421+
}
422+
self = lowerBound..<upperBound
423+
}
424+
425+
@inlinable
426+
public func encode(to encoder: Encoder) throws {
427+
var container = encoder.container(keyedBy: CodingKeys.self)
428+
try container.encode(self.lowerBound, forKey: .from)
429+
try container.encode(self.upperBound, forKey: .upTo)
430+
}
431+
}
432+
408433
/// A partial half-open interval up to, but not including, an upper bound.
409434
///
410435
/// You create `PartialRangeUpTo` instances by using the prefix half-open range
@@ -447,6 +472,24 @@ extension PartialRangeUpTo: RangeExpression {
447472
}
448473
}
449474

475+
extension PartialRangeUpTo: Codable where Bound: Codable {
476+
private enum CodingKeys: String, CodingKey {
477+
case beginningUpTo
478+
}
479+
480+
@inlinable
481+
public init(from decoder: Decoder) throws {
482+
let container = try decoder.container(keyedBy: CodingKeys.self)
483+
self = ..<try container.decode(Bound.self, forKey: .beginningUpTo)
484+
}
485+
486+
@inlinable
487+
public func encode(to encoder: Encoder) throws {
488+
var container = encoder.container(keyedBy: CodingKeys.self)
489+
try container.encode(self.upperBound, forKey: .beginningUpTo)
490+
}
491+
}
492+
450493
/// A partial interval up to, and including, an upper bound.
451494
///
452495
/// You create `PartialRangeThrough` instances by using the prefix closed range
@@ -488,6 +531,24 @@ extension PartialRangeThrough: RangeExpression {
488531
}
489532
}
490533

534+
extension PartialRangeThrough: Codable where Bound: Codable {
535+
private enum CodingKeys: String, CodingKey {
536+
case beginningTo
537+
}
538+
539+
@inlinable
540+
public init(from decoder: Decoder) throws {
541+
let container = try decoder.container(keyedBy: CodingKeys.self)
542+
self = ...try container.decode(Bound.self, forKey: .beginningTo)
543+
}
544+
545+
@inlinable
546+
public func encode(to encoder: Encoder) throws {
547+
var container = encoder.container(keyedBy: CodingKeys.self)
548+
try container.encode(self.upperBound, forKey: .beginningTo)
549+
}
550+
}
551+
491552
/// A partial interval extending upward from a lower bound.
492553
///
493554
/// You create `PartialRangeFrom` instances by using the postfix range operator
@@ -624,6 +685,24 @@ extension PartialRangeFrom: Sequence
624685
}
625686
}
626687

688+
extension PartialRangeFrom: Codable where Bound: Codable {
689+
private enum CodingKeys: String, CodingKey {
690+
case toEndFrom
691+
}
692+
693+
@inlinable
694+
public init(from decoder: Decoder) throws {
695+
let container = try decoder.container(keyedBy: CodingKeys.self)
696+
self = try container.decode(Bound.self, forKey: .toEndFrom)...
697+
}
698+
699+
@inlinable
700+
public func encode(to encoder: Encoder) throws {
701+
var container = encoder.container(keyedBy: CodingKeys.self)
702+
try container.encode(self.lowerBound, forKey: .toEndFrom)
703+
}
704+
}
705+
627706
extension Comparable {
628707
/// Returns a half-open range that contains its lower bound but not its upper
629708
/// bound.

0 commit comments

Comments
 (0)