File tree Expand file tree Collapse file tree 3 files changed +65
-0
lines changed
sources/declarative/decodable Expand file tree Collapse file tree 3 files changed +65
-0
lines changed Original file line number Diff line number Diff line change @@ -60,4 +60,22 @@ extension CSVDecoder {
6060 let source = ShadowDecoder . Source ( reader: reader, configuration: self . configuration, userInfo: self . userInfo)
6161 return try T ( from: ShadowDecoder ( source: source, codingPath: [ ] ) )
6262 }
63+
64+ /// Returns a sequence for decoding each row from a CSV file (given as a `Data` blob).
65+ /// - parameter data: The data blob representing a CSV file.
66+ /// - throws: `CSVError<CSVReader>` exclusively.
67+ open func lazy( from data: Data ) throws -> LazySequence {
68+ let reader = try CSVReader ( input: data, configuration: self . configuration. readerConfiguration)
69+ let source = ShadowDecoder . Source ( reader: reader, configuration: self . configuration, userInfo: self . userInfo)
70+ return LazySequence ( source: source)
71+ }
72+
73+ /// Returns a sequence for decoding each row from a CSV file (being pointed by `url`).
74+ /// - parameter url: The URL pointing to the file to decode.
75+ /// - throws: `CSVError<CSVReader>` exclusively.
76+ open func lazy( from url: URL ) throws -> LazySequence {
77+ let reader = try CSVReader ( input: url, configuration: self . configuration. readerConfiguration)
78+ let source = ShadowDecoder . Source ( reader: reader, configuration: self . configuration, userInfo: self . userInfo)
79+ return LazySequence ( source: source)
80+ }
6381}
Original file line number Diff line number Diff line change 1+ extension CSVDecoder {
2+ public struct LazySequence : IteratorProtocol , Sequence {
3+ private let source : ShadowDecoder . Source
4+ private var currentIndex : Int = 0
5+
6+ init ( source: ShadowDecoder . Source ) {
7+ self . source = source
8+ }
9+
10+ /// Advances to the next row and returns a `LazySequence.Row`, or `nil` if no next row exists.
11+ public mutating func next( ) -> Row ? {
12+ guard !self . source. isRowAtEnd ( index: self . currentIndex) else {
13+ return nil
14+ }
15+
16+ defer { self . currentIndex += 1 }
17+ let decoder = ShadowDecoder ( source: source, codingPath: [ IndexKey ( self . currentIndex) ] )
18+ return Row ( decoder: decoder)
19+ }
20+
21+ public struct Row {
22+ /// The representation of the decoding process point-in-time.
23+ private let decoder : ShadowDecoder
24+
25+ fileprivate init ( decoder: ShadowDecoder ) {
26+ self . decoder = decoder
27+ }
28+
29+ /// Returns a value of the type you specify, decoded from CSV row.
30+ /// - parameter type: The type of the value to decode from the supplied file.
31+ /// - throws: `DecodingError`, or `CSVError<CSVReader>`, or the error raised by your custom types.
32+ public func decode< T: Decodable > ( _ type: T . Type ) throws -> T {
33+ return try T ( from: decoder)
34+ }
35+ }
36+ }
37+ }
Original file line number Diff line number Diff line change @@ -91,6 +91,16 @@ extension DecodingRegularUsageTests {
9191 XCTAssertEqual ( pet. gender? . rawValue ?? " " , testPet [ 3 ] )
9292 XCTAssertEqual ( pet. animal, testPet [ 4 ] )
9393 }
94+
95+ for (index, row) in try decoder. lazy ( from: input) . enumerated ( ) {
96+ let pet = try row. decode ( Pet . self)
97+ let testPet = TestData . content [ index]
98+ XCTAssertEqual ( pet. sequence, Int ( testPet [ 0 ] ) !)
99+ XCTAssertEqual ( pet. name, testPet [ 1 ] )
100+ XCTAssertEqual ( pet. age, Double ( testPet [ 2 ] ) !)
101+ XCTAssertEqual ( pet. gender? . rawValue ?? " " , testPet [ 3 ] )
102+ XCTAssertEqual ( pet. animal, testPet [ 4 ] )
103+ }
94104 }
95105 }
96106
You can’t perform that action at this time.
0 commit comments