Created aysnc CSV encoder
This commit is contained in:
parent
9896bd77df
commit
a4444ffef3
|
@ -12,9 +12,59 @@ public final class CSVCoder {
|
|||
public func decode<T>(_ data: Data, to type: T.Type = T.self)throws -> [T] where T: Decodable {
|
||||
return try _CSVDecoder(csv: Array(data), decodingOptions: self.decodingOptions).decode(T.self, from: data)
|
||||
}
|
||||
|
||||
public func encode<T>(_ objects: [T], boolEncoding: BoolEncodingStrategy = .toString, stringEncoding: String.Encoding = .utf32)throws -> Data where T: Encodable {
|
||||
return try Data(_CSVEncoder.encode(objects, boolEncoding: boolEncoding, stringEncoding: stringEncoding))
|
||||
|
||||
public func encode<T>(_ objects: [T])throws -> Data where T: Encodable {
|
||||
return try Data(_CSVEncoder.encode(objects, encodingOptions: self.encodingOptions))
|
||||
}
|
||||
}
|
||||
|
||||
public final class CSVEncoder {
|
||||
public var encodingOptions: CSVCodingOptions
|
||||
|
||||
public init(encodingOptions: CSVCodingOptions) {
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
public var sync: CSVSyncEncoder {
|
||||
return CSVSyncEncoder(encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
public func async(_ onRow: @escaping ([UInt8]) -> ()) -> CSVAsyncEncoder {
|
||||
return CSVAsyncEncoder(encodingOptions: self.encodingOptions, onRow: onRow)
|
||||
}
|
||||
}
|
||||
|
||||
public final class CSVSyncEncoder {
|
||||
internal var encodingOptions: CSVCodingOptions
|
||||
|
||||
internal init(encodingOptions: CSVCodingOptions) {
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
public func encode<T>(_ objects: [T])throws -> Data where T: Encodable {
|
||||
var rows: [[UInt8]] = []
|
||||
rows.reserveCapacity(objects.count)
|
||||
|
||||
let encoder = AsyncEncoder(encodingOptions: self.encodingOptions) { row in
|
||||
rows.append(row)
|
||||
}
|
||||
try objects.forEach(encoder.encode)
|
||||
|
||||
return Data(rows.joined(separator: [CSV.Delimiter.newLine]))
|
||||
}
|
||||
}
|
||||
|
||||
public final class CSVAsyncEncoder {
|
||||
internal var encodingOptions: CSVCodingOptions
|
||||
private var encoder: AsyncEncoder
|
||||
|
||||
internal init(encodingOptions: CSVCodingOptions, onRow: @escaping ([UInt8]) -> ()) {
|
||||
self.encodingOptions = encodingOptions
|
||||
self.encoder = AsyncEncoder(encodingOptions: encodingOptions, onRow: onRow)
|
||||
}
|
||||
|
||||
public func encode<T>(_ object: T)throws where T: Encodable {
|
||||
try self.encoder.encode(object)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import Foundation
|
||||
|
||||
final class AsyncEncoder: Encoder {
|
||||
let codingPath: [CodingKey]
|
||||
let userInfo: [CodingUserInfoKey : Any]
|
||||
let container: DataContainer
|
||||
let encodingOptions: CSVCodingOptions
|
||||
let onRow: ([UInt8]) -> ()
|
||||
|
||||
init(
|
||||
path: CodingPath = [],
|
||||
info: [CodingUserInfoKey : Any] = [:],
|
||||
encodingOptions: CSVCodingOptions,
|
||||
onRow: @escaping ([UInt8]) -> ()
|
||||
) {
|
||||
self.codingPath = path
|
||||
self.userInfo = info
|
||||
self.container = DataContainer(section: .header)
|
||||
self.encodingOptions = encodingOptions
|
||||
self.onRow = onRow
|
||||
}
|
||||
|
||||
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
|
||||
let container = AsyncKeyedEncoder<Key>(path: self.codingPath, encoder: self)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func unkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return AsyncUnkeyedEncoder(encoder: self)
|
||||
}
|
||||
|
||||
func singleValueContainer() -> SingleValueEncodingContainer {
|
||||
return AsyncSingleValueEncoder(path: self.codingPath, encoder: self)
|
||||
}
|
||||
|
||||
func encode<T>(
|
||||
_ object: T
|
||||
)throws where T: Encodable {
|
||||
switch self.container.section {
|
||||
case .header:
|
||||
try object.encode(to: self)
|
||||
self.onRow(Array(self.container.cells.joined()))
|
||||
self.container.section = .row
|
||||
self.container.rowCount += 1
|
||||
self.container.cells = []
|
||||
fallthrough
|
||||
case .row:
|
||||
try object.encode(to: self)
|
||||
self.onRow(Array(self.container.cells.joined()))
|
||||
self.container.rowCount += 1
|
||||
self.container.cells = []
|
||||
}
|
||||
}
|
||||
|
||||
enum EncodingSection {
|
||||
case header
|
||||
case row
|
||||
}
|
||||
|
||||
final class DataContainer {
|
||||
var cells: [[UInt8]]
|
||||
var section: EncodingSection
|
||||
var rowCount: Int
|
||||
|
||||
init(cells: [[UInt8]] = [], section: EncodingSection = .row) {
|
||||
self.cells = cells
|
||||
self.section = section
|
||||
self.rowCount = 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
import Foundation
|
||||
|
||||
final class AsyncKeyedEncoder<K>: KeyedEncodingContainerProtocol where K: CodingKey {
|
||||
var codingPath: [CodingKey]
|
||||
var encoder: AsyncEncoder
|
||||
|
||||
init(path: CodingPath, encoder: AsyncEncoder) {
|
||||
self.codingPath = path
|
||||
self.encoder = encoder
|
||||
}
|
||||
|
||||
func _encode(_ value: [UInt8], for key: K) {
|
||||
switch self.encoder.container.section {
|
||||
case .header: self.encoder.container.cells.append(key.stringValue.bytes)
|
||||
case .row: self.encoder.container.cells.append(value)
|
||||
}
|
||||
}
|
||||
|
||||
func encodeNil(forKey key: K) throws {
|
||||
let value = self.encoder.encodingOptions.nilCodingStrategy.bytes()
|
||||
self._encode(value, for: key)
|
||||
}
|
||||
func encode(_ value: Bool, forKey key: K) throws {
|
||||
let value = self.encoder.encodingOptions.boolCodingStrategy.bytes(from: value)
|
||||
self._encode(value, for: key)
|
||||
}
|
||||
func encode(_ value: Double, forKey key: K) throws { self._encode(value.bytes, for: key) }
|
||||
func encode(_ value: Float, forKey key: K) throws { self._encode(value.bytes, for: key) }
|
||||
func encode(_ value: Int, forKey key: K) throws { self._encode(value.bytes, for: key) }
|
||||
func encode(_ value: String, forKey key: K) throws { self._encode(value.bytes, for: key) }
|
||||
|
||||
func encode<T>(_ value: T, forKey key: K) throws where T : Encodable {
|
||||
let encoder = AsyncEncoder(encodingOptions: self.encoder.encodingOptions, onRow: self.encoder.onRow)
|
||||
try value.encode(to: encoder)
|
||||
self._encode(encoder.container.cells[0], for: key)
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: K) -> KeyedEncodingContainer<NestedKey>
|
||||
where NestedKey : CodingKey
|
||||
{
|
||||
let container = AsyncKeyedEncoder<NestedKey>(path: self.codingPath + [key], encoder: self.encoder)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer(forKey key: K) -> UnkeyedEncodingContainer {
|
||||
return AsyncUnkeyedEncoder(encoder: self.encoder)
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return self.encoder
|
||||
}
|
||||
|
||||
func superEncoder(forKey key: K) -> Encoder {
|
||||
return encoder
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import Foundation
|
||||
|
||||
final class AsyncSingleValueEncoder: SingleValueEncodingContainer {
|
||||
let codingPath: [CodingKey]
|
||||
let encoder: AsyncEncoder
|
||||
|
||||
init(path: CodingPath, encoder: AsyncEncoder) {
|
||||
self.codingPath = path
|
||||
self.encoder = encoder
|
||||
}
|
||||
|
||||
func encodeNil() throws {
|
||||
let value = self.encoder.encodingOptions.nilCodingStrategy.bytes()
|
||||
self.encoder.container.cells.append(value)
|
||||
}
|
||||
func encode(_ value: Bool) throws {
|
||||
let value = self.encoder.encodingOptions.boolCodingStrategy.bytes(from: value)
|
||||
self.encoder.container.cells.append(value)
|
||||
}
|
||||
func encode(_ value: String) throws { self.encoder.container.cells.append(value.bytes) }
|
||||
func encode(_ value: Double) throws { self.encoder.container.cells.append(value.bytes) }
|
||||
func encode(_ value: Float) throws { self.encoder.container.cells.append(value.bytes) }
|
||||
func encode(_ value: Int) throws { self.encoder.container.cells.append(value.bytes) }
|
||||
|
||||
func encode<T>(_ value: T) throws where T : Encodable {
|
||||
let column = self.codingPath.map { $0.stringValue }.joined(separator: ".")
|
||||
throw EncodingError.invalidValue(value, EncodingError.Context(
|
||||
codingPath: self.codingPath,
|
||||
debugDescription: "Cannot encode nested data into cell in column '\(column)'"
|
||||
))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import Foundation
|
||||
|
||||
final class AsyncUnkeyedEncoder: UnkeyedEncodingContainer {
|
||||
var codingPath: [CodingKey]
|
||||
var encoder: AsyncEncoder
|
||||
|
||||
init(encoder: AsyncEncoder) {
|
||||
self.encoder = encoder
|
||||
self.codingPath = []
|
||||
}
|
||||
|
||||
var count: Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func fail(with value: Any) -> Error {
|
||||
return EncodingError.invalidValue(value, EncodingError.Context(
|
||||
codingPath: [],
|
||||
debugDescription: "Cannot use CSV decoder to decode array values"
|
||||
))
|
||||
}
|
||||
|
||||
func encodeNil() throws { throw self.fail(with: Optional<Any>.none as Any) }
|
||||
func encode(_ value: Bool) throws { throw self.fail(with: value) }
|
||||
func encode(_ value: String) throws { throw self.fail(with: value) }
|
||||
func encode(_ value: Double) throws { throw self.fail(with: value) }
|
||||
func encode(_ value: Float) throws { throw self.fail(with: value) }
|
||||
func encode(_ value: Int) throws { throw self.fail(with: value) }
|
||||
func encode<T>(_ value: T) throws where T : Encodable { throw self.fail(with: value) }
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey>
|
||||
where NestedKey : CodingKey
|
||||
{
|
||||
let container = AsyncKeyedEncoder<NestedKey>(path: self.codingPath, encoder: self.encoder)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return AsyncUnkeyedEncoder(encoder: self.encoder)
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return encoder
|
||||
}
|
||||
}
|
|
@ -4,38 +4,35 @@ final class _CSVEncoder: Encoder {
|
|||
let codingPath: [CodingKey]
|
||||
let userInfo: [CodingUserInfoKey : Any]
|
||||
let container: DataContainer
|
||||
let boolEncoding: BoolEncodingStrategy
|
||||
let stringEncoding: String.Encoding
|
||||
let encodingOptions: CSVCodingOptions
|
||||
|
||||
init(
|
||||
container: DataContainer,
|
||||
path: CodingPath = [],
|
||||
info: [CodingUserInfoKey : Any] = [:],
|
||||
boolEncoding: BoolEncodingStrategy = .toString,
|
||||
stringEncoding: String.Encoding = .utf8
|
||||
encodingOptions: CSVCodingOptions
|
||||
) {
|
||||
self.codingPath = path
|
||||
self.userInfo = info
|
||||
self.container = container
|
||||
self.boolEncoding = boolEncoding
|
||||
self.stringEncoding = stringEncoding
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
|
||||
let container = _CSVKeyedEncoder<Key>(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
let container = _CSVKeyedEncoder<Key>(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func unkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
func singleValueContainer() -> SingleValueEncodingContainer {
|
||||
return _CSVSingleValueEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVSingleValueEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
static func encode<T>(_ objects: [T], boolEncoding: BoolEncodingStrategy, stringEncoding: String.Encoding)throws -> [UInt8] where T: Encodable {
|
||||
let encoder = _CSVEncoder(container: DataContainer(), boolEncoding: boolEncoding, stringEncoding: stringEncoding)
|
||||
static func encode<T>(_ objects: [T], encodingOptions: CSVCodingOptions)throws -> [UInt8] where T: Encodable {
|
||||
let encoder = _CSVEncoder(container: DataContainer(), encodingOptions: encodingOptions)
|
||||
try objects.encode(to: encoder)
|
||||
return encoder.container.data
|
||||
}
|
|
@ -1,16 +1,14 @@
|
|||
import Foundation
|
||||
|
||||
final class _CSVKeyedEncoder<K>: KeyedEncodingContainerProtocol where K: CodingKey {
|
||||
var codingPath: [CodingKey]
|
||||
let codingPath: [CodingKey]
|
||||
let container: DataContainer
|
||||
let boolEncoding: BoolEncodingStrategy
|
||||
let stringEncoding: String.Encoding
|
||||
let encodingOptions: CSVCodingOptions
|
||||
|
||||
init(container: DataContainer, path: CodingPath, boolEncoding: BoolEncodingStrategy, stringEncoding: String.Encoding) {
|
||||
init(container: DataContainer, path: CodingPath, encodingOptions: CSVCodingOptions) {
|
||||
self.container = container
|
||||
self.codingPath = path
|
||||
self.boolEncoding = boolEncoding
|
||||
self.stringEncoding = stringEncoding
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
func titleEncode(for key: K, converter: ()throws -> [UInt8])rethrows {
|
||||
|
@ -24,8 +22,14 @@ final class _CSVKeyedEncoder<K>: KeyedEncodingContainerProtocol where K: CodingK
|
|||
}
|
||||
}
|
||||
|
||||
func encodeNil(forKey key: K) throws { self.titleEncode(for: key) { [] } }
|
||||
func encode(_ value: Bool, forKey key: K) throws { self.titleEncode(for: key) { self.boolEncoding.convert(value) } }
|
||||
func encodeNil(forKey key: K) throws {
|
||||
let value = self.encodingOptions.nilCodingStrategy.bytes()
|
||||
self.titleEncode(for: key) { value }
|
||||
}
|
||||
func encode(_ value: Bool, forKey key: K) throws {
|
||||
let value = self.encodingOptions.boolCodingStrategy.bytes(from: value)
|
||||
self.titleEncode(for: key) { value }
|
||||
}
|
||||
func encode(_ value: Double, forKey key: K) throws { self.titleEncode(for: key) { value.bytes } }
|
||||
func encode(_ value: Float, forKey key: K) throws { self.titleEncode(for: key) { value.bytes } }
|
||||
func encode(_ value: Int, forKey key: K) throws { self.titleEncode(for: key) { value.bytes } }
|
||||
|
@ -33,26 +37,34 @@ final class _CSVKeyedEncoder<K>: KeyedEncodingContainerProtocol where K: CodingK
|
|||
|
||||
func encode<T>(_ value: T, forKey key: K) throws where T : Encodable {
|
||||
try self.titleEncode(for: key) {
|
||||
let encoder = _CSVEncoder(container: DataContainer(titles: true), path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
let encoder = _CSVEncoder(
|
||||
container: DataContainer(titles: true),
|
||||
path: self.codingPath,
|
||||
encodingOptions: self.encodingOptions
|
||||
)
|
||||
try value.encode(to: encoder)
|
||||
return encoder.container.data
|
||||
}
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: K) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||
let container = _CSVKeyedEncoder<NestedKey>(container: self.container, path: self.codingPath + [key], boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
let container = _CSVKeyedEncoder<NestedKey>(
|
||||
container: self.container,
|
||||
path: self.codingPath + [key],
|
||||
encodingOptions: self.encodingOptions
|
||||
)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer(forKey key: K) -> UnkeyedEncodingContainer {
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
func superEncoder(forKey key: K) -> Encoder {
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath + [key], boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath + [key], encodingOptions: self.encodingOptions)
|
||||
}
|
||||
}
|
|
@ -3,18 +3,20 @@ import Foundation
|
|||
final class _CSVSingleValueEncoder: SingleValueEncodingContainer {
|
||||
let codingPath: [CodingKey]
|
||||
let container: DataContainer
|
||||
let boolEncoding: BoolEncodingStrategy
|
||||
let stringEncoding: String.Encoding
|
||||
let encodingOptions: CSVCodingOptions
|
||||
|
||||
init(container: DataContainer, path: CodingPath, boolEncoding: BoolEncodingStrategy, stringEncoding: String.Encoding) {
|
||||
init(container: DataContainer, path: CodingPath, encodingOptions: CSVCodingOptions) {
|
||||
self.codingPath = path
|
||||
self.container = container
|
||||
self.boolEncoding = boolEncoding
|
||||
self.stringEncoding = stringEncoding
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
func encodeNil() throws { self.container.data = [] }
|
||||
func encode(_ value: Bool) throws { self.container.data = boolEncoding.convert(value) }
|
||||
func encodeNil() throws {
|
||||
self.container.data = self.encodingOptions.nilCodingStrategy.bytes()
|
||||
}
|
||||
func encode(_ value: Bool) throws {
|
||||
self.container.data = self.encodingOptions.boolCodingStrategy.bytes(from: value)
|
||||
}
|
||||
func encode(_ value: String) throws { self.container.data = value.bytes }
|
||||
func encode(_ value: Double) throws { self.container.data = value.bytes }
|
||||
func encode(_ value: Float) throws { self.container.data = value.bytes }
|
|
@ -3,14 +3,12 @@ import Foundation
|
|||
final class _CSVUnkeyedEncoder: UnkeyedEncodingContainer {
|
||||
var codingPath: [CodingKey]
|
||||
let container: DataContainer
|
||||
let boolEncoding: BoolEncodingStrategy
|
||||
let stringEncoding: String.Encoding
|
||||
let encodingOptions: CSVCodingOptions
|
||||
|
||||
init(container: DataContainer, path: CodingPath, boolEncoding: BoolEncodingStrategy, stringEncoding: String.Encoding) {
|
||||
init(container: DataContainer, path: CodingPath, encodingOptions: CSVCodingOptions) {
|
||||
self.container = container
|
||||
self.codingPath = path
|
||||
self.boolEncoding = boolEncoding
|
||||
self.stringEncoding = stringEncoding
|
||||
self.encodingOptions = encodingOptions
|
||||
}
|
||||
|
||||
var count: Int {
|
||||
|
@ -29,21 +27,29 @@ final class _CSVUnkeyedEncoder: UnkeyedEncodingContainer {
|
|||
func encode(_ value: Int) throws { throw self.fail(with: value) }
|
||||
|
||||
func encode<T>(_ value: T) throws where T : Encodable {
|
||||
let encoder = _CSVEncoder(container: DataContainer(titles: self.container.data.count > 0), path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
let encoder = _CSVEncoder(
|
||||
container: DataContainer(titles: self.container.data.count > 0),
|
||||
path: self.codingPath,
|
||||
encodingOptions: self.encodingOptions
|
||||
)
|
||||
try value.encode(to: encoder)
|
||||
self.container.data.append(contentsOf: encoder.container.data.dropLast() + ["\n"])
|
||||
}
|
||||
|
||||
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||
let container = _CSVKeyedEncoder<NestedKey>(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
let container = _CSVKeyedEncoder<NestedKey>(
|
||||
container: self.container,
|
||||
path: self.codingPath,
|
||||
encodingOptions: self.encodingOptions
|
||||
)
|
||||
return KeyedEncodingContainer(container)
|
||||
}
|
||||
|
||||
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVUnkeyedEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
|
||||
func superEncoder() -> Encoder {
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath, boolEncoding: self.boolEncoding, stringEncoding: self.stringEncoding)
|
||||
return _CSVEncoder(container: self.container, path: self.codingPath, encodingOptions: self.encodingOptions)
|
||||
}
|
||||
}
|
|
@ -160,7 +160,7 @@ class CSVTests: XCTestCase {
|
|||
let decoder = CSVCoder(decodingOptions: decodingOptions)
|
||||
|
||||
let fielders = try decoder.decode(data, to: Response.self)
|
||||
_ = try decoder.encode(fielders, boolEncoding: .custom(true: "Yes".bytes, false: "No".bytes))
|
||||
_ = try decoder.encode(fielders)
|
||||
}
|
||||
|
||||
func testCSVEncodingSpeed()throws {
|
||||
|
@ -172,14 +172,34 @@ class CSVTests: XCTestCase {
|
|||
|
||||
let fielders = try decoder.decode(data, to: Response.self)
|
||||
|
||||
// 7.391
|
||||
// 9.477
|
||||
measure {
|
||||
do {
|
||||
_ = try decoder.encode(fielders)
|
||||
} catch { XCTFail(error.localizedDescription) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testCSVSyncEncodingSpeed() throws {
|
||||
let url = URL(string: "file:/Users/calebkleveter/Development/developer_survey_2018.csv")!
|
||||
let data = try Data(contentsOf: url)
|
||||
|
||||
let decodingOptions = CSVCodingOptions(boolCodingStrategy: .fuzzy, nilCodingStrategy: .custom("NA"))
|
||||
let decoder = CSVDecoder(decodingOptions: decodingOptions)
|
||||
|
||||
let fielders = try decoder.sync.decode(Response.self, from: data)
|
||||
|
||||
let encodingOptions = CSVCodingOptions(boolCodingStrategy: .fuzzy, nilCodingStrategy: .custom("NA"))
|
||||
let encoder = CSVEncoder(encodingOptions: encodingOptions)
|
||||
|
||||
// 5.908
|
||||
measure {
|
||||
do {
|
||||
_ = try encoder.sync.encode(fielders)
|
||||
} catch { XCTFail(error.localizedDescription) }
|
||||
}
|
||||
}
|
||||
|
||||
func testDataToIntSpeed() {
|
||||
let bytes = "12495768014".bytes
|
||||
measure {
|
||||
|
|
Loading…
Reference in New Issue