File tree Expand file tree Collapse file tree 3 files changed +59
-0
lines changed
sources/declarative/decodable Expand file tree Collapse file tree 3 files changed +59
-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 -> CSVDecoderSequence {
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 CSVDecoderSequence ( 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 -> CSVDecoderSequence {
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 CSVDecoderSequence ( source: source)
80+ }
6381}
Original file line number Diff line number Diff line change 1+ open class CSVDecoderSequence : IteratorProtocol , Sequence {
2+ private let source : ShadowDecoder . Source
3+ private var currentIndex : Int = 0
4+
5+ init ( source: ShadowDecoder . Source ) {
6+ self . source = source
7+ }
8+
9+ /// Advances to the next row and returns a `CSVRowDecoder`, or `nil` if no next row exists.
10+ public func next( ) -> CSVRowDecoder ? {
11+ guard !self . source. isRowAtEnd ( index: self . currentIndex) else {
12+ return nil
13+ }
14+
15+ defer { self . currentIndex += 1 }
16+ let decoder = ShadowDecoder ( source: source, codingPath: [ IndexKey ( self . currentIndex) ] )
17+ return CSVRowDecoder ( decoder: decoder)
18+ }
19+ }
20+
21+ public struct CSVRowDecoder {
22+ /// The representation of the decoding process point-in-time.
23+ let decoder : ShadowDecoder
24+
25+ /// Returns a value of the type you specify, decoded from CSV row.
26+ /// - parameter type: The type of the value to decode from the supplied file.
27+ /// - throws: `DecodingError`, or `CSVError<CSVReader>`, or the error raised by your custom types.
28+ public func decode< T: Decodable > ( _ type: T . Type ) throws -> T {
29+ return try T ( from: decoder)
30+ }
31+ }
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