Skip to content

Commit 7052679

Browse files
committed
Unwrap ScalarIterator into ScalarDecoder
1 parent 8dfa886 commit 7052679

File tree

5 files changed

+143
-145
lines changed

5 files changed

+143
-145
lines changed

Sources/Active/Reader/Reader.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ public final class CSVReader: IteratorProtocol, Sequence {
1515
private(set) internal var headerLookup: [Int:Int]?
1616
/// Unicode scalar buffer to keep scalars that hasn't yet been analysed.
1717
private let buffer: ScalarBuffer
18-
/// The unicode scalar iterator providing all input data.
19-
private let iterator: ScalarIterator
18+
/// The unicode scalar decoder providing all input data.
19+
private let decoder: ScalarDecoder
2020
/// Check whether the given unicode scalar is part of the field delimiter sequence.
2121
private let isFieldDelimiter: DelimiterChecker
2222
/// Check whether the given unicode scalar is par of the row delimiter sequence.
@@ -35,16 +35,16 @@ public final class CSVReader: IteratorProtocol, Sequence {
3535
/// Designated initializer for the CSV reader.
3636
/// - parameter configuration: Recipe detailing how to parse the CSV data (i.e. encoding, delimiters, etc.).
3737
/// - parameter buffer: A buffer storing in-flight `Unicode.Scalar`s.
38-
/// - parameter iterator: An iterator providing the CSV `Unicode.Scalar`s.
38+
/// - parameter decoder: The instance providing the input `Unicode.Scalar`s.
3939
/// - throws: `CSVError<CSVReader>` exclusively.
40-
internal init(configuration: Configuration, buffer: ScalarBuffer, iterator: ScalarIterator) throws {
40+
internal init(configuration: Configuration, buffer: ScalarBuffer, decoder: @escaping ScalarDecoder) throws {
4141
self.configuration = configuration
42-
self.settings = try Settings(configuration: configuration, iterator: iterator, buffer: buffer)
42+
self.settings = try Settings(configuration: configuration, decoder: decoder, buffer: buffer)
4343
(self.headers, self.headerLookup) = (.init(), nil)
4444
self.buffer = buffer
45-
self.iterator = iterator
46-
self.isFieldDelimiter = CSVReader.makeMatcher(delimiter: self.settings.delimiters.field, buffer: self.buffer, iterator: self.iterator)
47-
self.isRowDelimiter = CSVReader.makeMatcher(delimiter: self.settings.delimiters.row, buffer: self.buffer, iterator: self.iterator)
45+
self.decoder = decoder
46+
self.isFieldDelimiter = CSVReader.makeMatcher(delimiter: self.settings.delimiters.field, buffer: self.buffer, decoder: self.decoder)
47+
self.isRowDelimiter = CSVReader.makeMatcher(delimiter: self.settings.delimiters.row, buffer: self.buffer, decoder: self.decoder)
4848
self.count = (0, 0)
4949
self.status = .reading
5050

@@ -148,7 +148,7 @@ extension CSVReader {
148148
// 1. This loops starts a row, and then continue for every field.
149149
loop: while true {
150150
// 2. Try to retrieve a scalar (if there is none, we reached the EOF).
151-
guard let scalar = try self.buffer.next() ?? self.iterator.next() else {
151+
guard let scalar = try self.buffer.next() ?? self.decoder() else {
152152
switch result.isEmpty {
153153
// 2.A. If no fields has been parsed, return nil.
154154
case true: return nil
@@ -196,7 +196,7 @@ extension CSVReader {
196196

197197
fieldLoop: while true {
198198
// Try to retrieve an scalar (if not, it is the EOF).
199-
guard let scalar = try self.buffer.next() ?? self.iterator.next() else { reachedRowsEnd = true; break fieldLoop }
199+
guard let scalar = try self.buffer.next() ?? self.decoder() else { reachedRowsEnd = true; break fieldLoop }
200200
// There cannot be double quotes on unescaped fields. If one is encountered, an error is thrown.
201201
if scalar == self.settings.escapingScalar {
202202
throw Error.invalidUnescapedField(rowIndex: rowIndex)
@@ -235,18 +235,18 @@ extension CSVReader {
235235

236236
fieldLoop: while true {
237237
// 1. Retrieve an scalar (if not there, it means EOF). This case is not allowed without closing the escaping field first.
238-
guard let scalar = try self.buffer.next() ?? self.iterator.next() else { throw Error.invalidEOF(rowIndex: rowIndex) }
238+
guard let scalar = try self.buffer.next() ?? self.decoder() else { throw Error.invalidEOF(rowIndex: rowIndex) }
239239
// 2. If the retrieved scalar is not a quote (i.e. "), just store it and continue parsing.
240240
guard scalar == self.settings.escapingScalar else { field.append(scalar); continue fieldLoop }
241241
// 3. If the retrieved scalar was a quote, retrieve the following scalar and check if it is EOF. If so, the field has finished and also the row and the file.
242-
guard var followingScalar = try self.buffer.next() ?? self.iterator.next() else { reachedRowsEnd = true; break fieldLoop }
242+
guard var followingScalar = try self.buffer.next() ?? self.decoder() else { reachedRowsEnd = true; break fieldLoop }
243243
// 4. If the second retrieved scalar is another quote, the data is escaping a single quote scalar (quotes are escaped with other quotes).
244244
guard followingScalar != self.settings.escapingScalar else { field.append(self.settings.escapingScalar); continue fieldLoop }
245245
// 5. Once this point is reached, the field has been properly escaped.
246246
if !self.settings.trimCharacters.isEmpty {
247247
// 6. Trim any character after the quote if necessary.
248248
while self.settings.trimCharacters.contains(followingScalar) {
249-
guard let tmpScalar = try self.buffer.next() ?? self.iterator.next() else {
249+
guard let tmpScalar = try self.buffer.next() ?? self.decoder() else {
250250
reachedRowsEnd = true
251251
break fieldLoop
252252
}

Sources/Active/Reader/ReaderAPI.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ extension CSVReader {
88
@_specialize(exported: true, where S==String)
99
public convenience init<S>(input: S, configuration: Configuration = .init()) throws where S:StringProtocol {
1010
let buffer = ScalarBuffer(reservingCapacity: 8)
11-
let iterator = ScalarIterator(scalarIterator: input.unicodeScalars.makeIterator())
12-
try self.init(configuration: configuration, buffer: buffer, iterator: iterator)
11+
let decoder = CSVReader.makeDecoder(from: input.unicodeScalars.makeIterator())
12+
try self.init(configuration: configuration, buffer: buffer, decoder: decoder)
1313
}
1414

1515
/// Creates a reader instance that will be used to parse the given data blob.
@@ -32,8 +32,8 @@ extension CSVReader {
3232
// B.2. Select the appropriate encoding depending from the user provided encoding (if any), and the BOM encoding (if any).
3333
let encoding = try String.Encoding.selectFrom(provided: configuration.encoding, inferred: inferredEncoding)
3434
// B.3. Create the scalar iterator producing all `Unicode.Scalar`s from the data bytes.
35-
let iterator = try ScalarIterator(iterator: dataIterator, encoding: encoding, firstBytes: unusedBytes)
36-
try self.init(configuration: configuration, buffer: buffer, iterator: iterator)
35+
let decoder = try CSVReader.makeDecoder(from: dataIterator, encoding: encoding, firstBytes: unusedBytes)
36+
try self.init(configuration: configuration, buffer: buffer, decoder: decoder)
3737
}
3838
}
3939

@@ -68,8 +68,8 @@ extension CSVReader {
6868

6969
// B.5. Create the scalar buffer & iterator producing all `Unicode.Scalar`s from the data bytes.
7070
let buffer = ScalarBuffer(reservingCapacity: 8)
71-
let iterator = try ScalarIterator(stream: stream, encoding: encoding, chunk: 1024, firstBytes: unusedBytes)
72-
try self.init(configuration: configuration, buffer: buffer, iterator: iterator)
71+
let decoder = try CSVReader.makeDecoder(from: stream, encoding: encoding, chunk: 1024, firstBytes: unusedBytes)
72+
try self.init(configuration: configuration, buffer: buffer, decoder: decoder)
7373
}
7474
}
7575
}

Sources/Active/Reader/ReaderConfiguration.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@ extension CSVReader {
4242

4343
/// Creates the inmutable reader settings from the user provided configuration values.
4444
/// - parameter configuration: The configuration values provided by the API user.
45-
/// - parameter iterator: The iterator providing `Unicode.Scalar` values.
45+
/// - parameter decoder: The instance providing the input `Unicode.Scalar`s.
4646
/// - parameter buffer: Small buffer use to store `Unicode.Scalar` values that have been read from the input, but haven't yet been processed.
4747
/// - throws: `CSVError<CSVReader>` exclusively.
48-
init(configuration: Configuration, iterator: ScalarIterator, buffer: ScalarBuffer) throws {
48+
init(configuration: Configuration, decoder: ScalarDecoder, buffer: ScalarBuffer) throws {
4949
// 1. Figure out the field and row delimiters.
5050
switch (configuration.delimiters.field.rawValue, configuration.delimiters.row.rawValue) {
5151
case (nil, nil):
52-
self.delimiters = try CSVReader.inferDelimiters(iterator: iterator, buffer: buffer)
52+
self.delimiters = try CSVReader.inferDelimiters(decoder: decoder, buffer: buffer)
5353
case (nil, let row):
54-
self.delimiters = try CSVReader.inferFieldDelimiter(rowDelimiter: row, iterator: iterator, buffer: buffer)
54+
self.delimiters = try CSVReader.inferFieldDelimiter(rowDelimiter: row, decoder: decoder, buffer: buffer)
5555
case (let field, nil):
56-
self.delimiters = try CSVReader.inferRowDelimiter(fieldDelimiter: field, iterator: iterator, buffer: buffer)
56+
self.delimiters = try CSVReader.inferRowDelimiter(fieldDelimiter: field, decoder: decoder, buffer: buffer)
5757
case (let field, let row) where !field.elementsEqual(row):
5858
self.delimiters = (field, row)
5959
case (let delimiter, _):

0 commit comments

Comments
 (0)