zlight_csv 0.4.0-aarch64-linux → 0.6.0-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ARCHITECTURE.md +132 -0
- data/CHANGELOG.md +149 -12
- data/LICENSE +1 -1
- data/README.md +108 -6
- data/VERSION +1 -1
- data/ext/zlight_csv/Cargo.toml +30 -0
- data/ext/zlight_csv/extconf.rb +16 -0
- data/ext/zlight_csv/src/convert.rs +203 -0
- data/ext/zlight_csv/src/error.rs +128 -0
- data/ext/zlight_csv/src/lib.rs +57 -0
- data/ext/zlight_csv/src/options.rs +143 -0
- data/ext/zlight_csv/src/reader.rs +26 -0
- data/ext/zlight_csv/src/row.rs +85 -0
- data/lib/zlight_csv/3.1/zlight_csv.so +0 -0
- data/lib/zlight_csv/3.2/zlight_csv.so +0 -0
- data/lib/zlight_csv/3.3/zlight_csv.so +0 -0
- data/lib/zlight_csv/3.4/zlight_csv.so +0 -0
- data/lib/zlight_csv/4.0/zlight_csv.so +0 -0
- data/lib/zlight_csv/errors.rb +20 -0
- data/lib/zlight_csv/native.rb +20 -0
- data/lib/zlight_csv.rb +135 -256
- metadata +39 -10
- data/lib/zlight_csv/3.0/zlight_csv.so +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ZLight
|
|
4
|
+
# Loads the compiled extension.
|
|
5
|
+
#
|
|
6
|
+
# A precompiled gem ships one shared library per Ruby minor version, laid out
|
|
7
|
+
# as lib/zlight_csv/<major.minor>/zlight_csv.<so|bundle|dll>, because a C
|
|
8
|
+
# extension built against one Ruby's ABI cannot be loaded by another. A gem
|
|
9
|
+
# built from source has a single library at lib/zlight_csv instead, so try
|
|
10
|
+
# the versioned path first and fall back.
|
|
11
|
+
module Native
|
|
12
|
+
def self.load!
|
|
13
|
+
require_relative "#{RUBY_VERSION[/\d+\.\d+/]}/zlight_csv"
|
|
14
|
+
rescue LoadError
|
|
15
|
+
require_relative 'zlight_csv'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
ZLight::Native.load!
|
data/lib/zlight_csv.rb
CHANGED
|
@@ -1,304 +1,183 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'zlight_csv/version'
|
|
4
|
+
require_relative 'zlight_csv/errors'
|
|
5
|
+
require_relative 'zlight_csv/native'
|
|
4
6
|
|
|
5
|
-
#
|
|
6
|
-
begin
|
|
7
|
-
ruby_version = RUBY_VERSION.match(/(\d+\.\d+)/)[1]
|
|
8
|
-
require_relative "zlight_csv/#{ruby_version}/zlight_csv"
|
|
9
|
-
rescue LoadError
|
|
10
|
-
require_relative 'zlight_csv/zlight_csv'
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# ZLight is a high-performance CSV parser for Ruby, powered by Rust.
|
|
14
|
-
#
|
|
15
|
-
# It provides a simple, Ruby CSV-compatible API for parsing CSV files
|
|
16
|
-
# up to 30x faster than the standard library.
|
|
17
|
-
#
|
|
18
|
-
# @example Basic parsing with headers
|
|
19
|
-
# result = ZLight.parse("name,age\nAlice,30\nBob,25")
|
|
20
|
-
# # => [{:name=>"Alice", :age=>"30"}, {:name=>"Bob", :age=>"25"}]
|
|
7
|
+
# ZLight is a CSV parser and writer for Ruby, implemented in Rust.
|
|
21
8
|
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
9
|
+
# The public API is deliberately small. Four of the methods below are defined
|
|
10
|
+
# in the native extension and four are defined here in Ruby as conveniences on
|
|
11
|
+
# top of them; which is which is noted on each.
|
|
25
12
|
#
|
|
26
|
-
# @example
|
|
27
|
-
#
|
|
28
|
-
# # => [["Alice", "30"], ["Bob", "25"]]
|
|
13
|
+
# @example Parse a string
|
|
14
|
+
# ZLight.parse("name,age\nAlice,30") # => [{name: "Alice", age: "30"}]
|
|
29
15
|
#
|
|
30
|
-
# @example
|
|
31
|
-
#
|
|
16
|
+
# @example Parse a file, converting numbers
|
|
17
|
+
# ZLight.read("users.csv", converters: :numeric)
|
|
32
18
|
#
|
|
33
|
-
# @example
|
|
34
|
-
# ZLight.
|
|
35
|
-
# reader.each { |row| process(row) }
|
|
36
|
-
# end
|
|
19
|
+
# @example Stream a large file in constant memory
|
|
20
|
+
# ZLight.open("huge.csv") { |reader| reader.each { |row| process(row) } }
|
|
37
21
|
#
|
|
38
|
-
# @example
|
|
39
|
-
#
|
|
40
|
-
# reader.lazy.select { |row| row[:age] > 30 }.first(10)
|
|
41
|
-
# reader.close
|
|
22
|
+
# @example Write a file
|
|
23
|
+
# ZLight.write("out.csv", [{ name: "Alice", age: 30 }])
|
|
42
24
|
#
|
|
43
|
-
# @see https://github.com/
|
|
25
|
+
# @see https://github.com/codebyisaad/zlight
|
|
26
|
+
# @see file:README.md#differences-from-stdlib-csv Differences from stdlib CSV
|
|
44
27
|
module ZLight
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# @param converters [Symbol, nil] Set to :numeric for auto-conversion of integers/floats
|
|
64
|
-
# @param col_sep [String] Column separator character (default: ",")
|
|
65
|
-
# @param quote_char [String] Quote character for escaping (default: '"')
|
|
66
|
-
# @param flexible [Boolean] Allow variable-length records (default: true)
|
|
67
|
-
#
|
|
68
|
-
# @return [Array<Hash>] When headers: true, returns array of Hashes with Symbol keys
|
|
69
|
-
# @return [Array<Array>] When headers: false, returns array of Arrays
|
|
70
|
-
#
|
|
71
|
-
# @raise [ArgumentError] If options are invalid
|
|
72
|
-
# @raise [ZLight::ParseError] If CSV data is malformed
|
|
73
|
-
# @raise [ZLight::EncodingError] If headers contain invalid UTF-8
|
|
74
|
-
#
|
|
75
|
-
# @example Parse with headers (default)
|
|
76
|
-
# ZLight.parse("name,age\nAlice,30")
|
|
77
|
-
# # => [{:name=>"Alice", :age=>"30"}]
|
|
78
|
-
#
|
|
79
|
-
# @example Parse without headers
|
|
80
|
-
# ZLight.parse("Alice,30", headers: false)
|
|
81
|
-
# # => [["Alice", "30"]]
|
|
82
|
-
#
|
|
83
|
-
# @example Parse with numeric conversion
|
|
84
|
-
# ZLight.parse("name,age\nAlice,30", converters: :numeric)
|
|
85
|
-
# # => [{:name=>"Alice", :age=>30}]
|
|
86
|
-
#
|
|
87
|
-
# @example Parse TSV (tab-separated values)
|
|
88
|
-
# ZLight.parse("name\tage\nAlice\t30", col_sep: "\t")
|
|
89
|
-
# # => [{:name=>"Alice", :age=>"30"}]
|
|
90
|
-
#
|
|
91
|
-
# @note The parse method is defined in the Rust native extension.
|
|
92
|
-
# See ext/zlight_csv/src/lib.rs for implementation.
|
|
93
|
-
|
|
94
|
-
# Generates a CSV string from an array of rows.
|
|
95
|
-
#
|
|
96
|
-
# This method is implemented as a native Rust extension for maximum performance.
|
|
97
|
-
#
|
|
98
|
-
# @param rows [Array<Hash>, Array<Array>] The data to convert to CSV
|
|
99
|
-
# @param headers [Boolean] Write header row for hash input (default: true)
|
|
100
|
-
# @param col_sep [String] Column separator character (default: ",")
|
|
101
|
-
# @param quote_char [String] Quote character for escaping (default: '"')
|
|
102
|
-
# @param force_quotes [Boolean] Force quoting all fields (default: false)
|
|
103
|
-
#
|
|
104
|
-
# @return [String] The generated CSV string
|
|
105
|
-
#
|
|
106
|
-
# @raise [ArgumentError] If options are invalid or rows format is mixed
|
|
107
|
-
#
|
|
108
|
-
# @example Generate CSV from array of hashes
|
|
109
|
-
# ZLight.generate([{name: "Alice", age: 30}, {name: "Bob", age: 25}])
|
|
110
|
-
# # => "name,age\nAlice,30\nBob,25\n"
|
|
111
|
-
#
|
|
112
|
-
# @example Generate CSV from array of arrays (no headers)
|
|
113
|
-
# ZLight.generate([["Alice", 30], ["Bob", 25]])
|
|
114
|
-
# # => "Alice,30\nBob,25\n"
|
|
115
|
-
#
|
|
116
|
-
# @example Generate without headers
|
|
117
|
-
# ZLight.generate([{name: "Alice"}], headers: false)
|
|
118
|
-
# # => "Alice\n"
|
|
119
|
-
#
|
|
120
|
-
# @example Generate TSV
|
|
121
|
-
# ZLight.generate([{a: 1, b: 2}], col_sep: "\t")
|
|
122
|
-
# # => "a\tb\n1\t2\n"
|
|
123
|
-
#
|
|
124
|
-
# @note The generate method is defined in the Rust native extension.
|
|
125
|
-
# See ext/zlight_csv/src/writer.rs for implementation.
|
|
28
|
+
class << self
|
|
29
|
+
# @!method parse(csv_string, headers: true, converters: nil, col_sep: ",", quote_char: "\"", flexible: true)
|
|
30
|
+
# Parses a CSV string into an Array of rows.
|
|
31
|
+
#
|
|
32
|
+
# Defined in the native extension; see ext/zlight_csv/src/read/eager.rs.
|
|
33
|
+
# Reads Ruby's string buffer directly without copying it.
|
|
34
|
+
#
|
|
35
|
+
# @param csv_string [String] the CSV data
|
|
36
|
+
# @param headers [Boolean] treat the first row as headers, returning
|
|
37
|
+
# Hashes with Symbol keys; when false, rows are Arrays
|
|
38
|
+
# @param converters [Symbol, nil] `:numeric` converts integers and floats
|
|
39
|
+
# @param col_sep [String] single-byte column separator
|
|
40
|
+
# @param quote_char [String] single-byte quote character
|
|
41
|
+
# @param flexible [Boolean] allow rows with differing field counts
|
|
42
|
+
# @return [Array<Hash>, Array<Array>] one element per row
|
|
43
|
+
# @raise [ZLight::ParseError] if the CSV is malformed
|
|
44
|
+
# @raise [ZLight::EncodingError] if a header is not valid UTF-8
|
|
45
|
+
# @raise [ArgumentError] if an option is invalid
|
|
126
46
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
47
|
+
# @!method generate(rows, headers: true, col_sep: ",", quote_char: "\"", force_quotes: false)
|
|
48
|
+
# Builds a CSV string from an Array of rows.
|
|
49
|
+
#
|
|
50
|
+
# Defined in the native extension; see ext/zlight_csv/src/write/mod.rs.
|
|
51
|
+
# Accepts an Array of Hashes or an Array of Arrays, not a mix of both.
|
|
52
|
+
# For Hashes the column order comes from the keys of the first one.
|
|
53
|
+
#
|
|
54
|
+
# @param rows [Array<Hash>, Array<Array>] the rows to write
|
|
55
|
+
# @param headers [Boolean] emit a header row (Hash input only)
|
|
56
|
+
# @param col_sep [String] single-byte column separator
|
|
57
|
+
# @param quote_char [String] single-byte quote character
|
|
58
|
+
# @param force_quotes [Boolean] quote every field, not only those needing it
|
|
59
|
+
# @return [String] the generated CSV
|
|
60
|
+
# @raise [ArgumentError] if an option is invalid or the row types are mixed
|
|
132
61
|
|
|
133
|
-
|
|
134
|
-
#
|
|
62
|
+
# @!method stream(csv_string, **options)
|
|
63
|
+
# Returns a {ZLight::StreamReader} over a CSV string.
|
|
135
64
|
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
65
|
+
# Defined in the native extension; see ext/zlight_csv/src/read/stream.rs.
|
|
66
|
+
# Takes the same options as {.parse}.
|
|
138
67
|
#
|
|
139
|
-
#
|
|
140
|
-
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
# @param quote_char [String] Quote character for escaping (default: '"')
|
|
144
|
-
# @param flexible [Boolean] Allow variable-length records (default: true)
|
|
145
|
-
#
|
|
146
|
-
# @return [Array<Hash>] When headers: true, returns array of Hashes with Symbol keys
|
|
147
|
-
# @return [Array<Array>] When headers: false, returns array of Arrays
|
|
148
|
-
#
|
|
149
|
-
# @raise [Errno::ENOENT] If the file does not exist
|
|
150
|
-
# @raise [ArgumentError] If options are invalid
|
|
151
|
-
# @raise [ZLight::ParseError] If CSV data is malformed
|
|
68
|
+
# @return [ZLight::StreamReader] a single-pass reader
|
|
69
|
+
|
|
70
|
+
# @!method stream_file(path, **options)
|
|
71
|
+
# Returns a {ZLight::StreamReader} over a file.
|
|
152
72
|
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
73
|
+
# Defined in the native extension. The file is opened immediately, so a
|
|
74
|
+
# missing or unreadable path raises here rather than on the first read.
|
|
75
|
+
# Prefer {.open}, which closes the reader for you.
|
|
156
76
|
#
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
|
|
77
|
+
# @return [ZLight::StreamReader] a single-pass reader
|
|
78
|
+
# @raise [IOError] if the file does not exist or cannot be read
|
|
79
|
+
|
|
80
|
+
# Reads and parses a CSV file.
|
|
160
81
|
#
|
|
161
|
-
#
|
|
162
|
-
#
|
|
82
|
+
# Convenience wrapper: reads the file as UTF-8 and hands it to {.parse},
|
|
83
|
+
# so the whole file is held in memory. Use {.open} for large files.
|
|
163
84
|
#
|
|
85
|
+
# @param path [String] path to the CSV file
|
|
86
|
+
# @param options [Hash] any option accepted by {.parse}
|
|
87
|
+
# @return [Array<Hash>, Array<Array>] one element per row
|
|
88
|
+
# @raise [Errno::ENOENT] if the file does not exist
|
|
164
89
|
# @see .parse
|
|
165
90
|
def read(path, **options)
|
|
166
91
|
parse(File.read(path, encoding: 'UTF-8'), **options)
|
|
167
92
|
end
|
|
168
93
|
|
|
169
|
-
# Writes
|
|
170
|
-
#
|
|
171
|
-
# Convenience method that generates CSV and writes to disk.
|
|
172
|
-
# The file is written with UTF-8 encoding.
|
|
173
|
-
#
|
|
174
|
-
# @param path [String] Path to the output CSV file
|
|
175
|
-
# @param rows [Array<Hash>, Array<Array>] The data to write
|
|
176
|
-
# @param headers [Boolean] Write header row for hash input (default: true)
|
|
177
|
-
# @param col_sep [String] Column separator character (default: ",")
|
|
178
|
-
# @param quote_char [String] Quote character for escaping (default: '"')
|
|
179
|
-
# @param force_quotes [Boolean] Force quoting all fields (default: false)
|
|
180
|
-
#
|
|
181
|
-
# @return [Integer] Number of bytes written
|
|
182
|
-
#
|
|
183
|
-
# @raise [Errno::ENOENT] If the directory does not exist
|
|
184
|
-
# @raise [Errno::EACCES] If the file is not writable
|
|
185
|
-
# @raise [ArgumentError] If options are invalid
|
|
94
|
+
# Writes rows to a CSV file.
|
|
186
95
|
#
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
190
|
-
# @example Write arrays to CSV
|
|
191
|
-
# ZLight.write("data.csv", [["a", "b"], [1, 2]])
|
|
192
|
-
#
|
|
193
|
-
# @example Write TSV
|
|
194
|
-
# ZLight.write("data.tsv", rows, col_sep: "\t")
|
|
96
|
+
# Convenience wrapper around {.generate}. The CSV is built in memory before
|
|
97
|
+
# being written, so this is not suited to output larger than RAM.
|
|
195
98
|
#
|
|
99
|
+
# @param path [String] path to write to
|
|
100
|
+
# @param rows [Array<Hash>, Array<Array>] the rows to write
|
|
101
|
+
# @param options [Hash] any option accepted by {.generate}
|
|
102
|
+
# @return [Integer] bytes written
|
|
103
|
+
# @raise [Errno::ENOENT] if the directory does not exist
|
|
196
104
|
# @see .generate
|
|
197
105
|
def write(path, rows, **options)
|
|
198
106
|
File.write(path, generate(rows, **options), encoding: 'UTF-8')
|
|
199
107
|
end
|
|
200
108
|
|
|
201
|
-
# Iterates over
|
|
202
|
-
#
|
|
203
|
-
# When called with a block, yields each row and returns nil.
|
|
204
|
-
# When called without a block, returns an Enumerator for lazy iteration.
|
|
205
|
-
#
|
|
206
|
-
# @param csv_string [String] The CSV data to parse
|
|
207
|
-
# @param headers [Boolean] Treat first row as headers (default: true)
|
|
208
|
-
# @param converters [Symbol, nil] Set to :numeric for auto-conversion
|
|
209
|
-
# @param col_sep [String] Column separator character (default: ",")
|
|
210
|
-
# @param quote_char [String] Quote character for escaping (default: '"')
|
|
211
|
-
# @param flexible [Boolean] Allow variable-length records (default: true)
|
|
109
|
+
# Iterates over the rows of a CSV string.
|
|
212
110
|
#
|
|
213
|
-
#
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
# @return [nil] When a block is given
|
|
217
|
-
# @return [Enumerator] When no block is given, for lazy iteration
|
|
218
|
-
#
|
|
219
|
-
# @example Iterate with a block
|
|
220
|
-
# ZLight.foreach("name,age\nAlice,30\nBob,25") do |row|
|
|
221
|
-
# puts row[:name]
|
|
222
|
-
# end
|
|
223
|
-
# # Output:
|
|
224
|
-
# # Alice
|
|
225
|
-
# # Bob
|
|
226
|
-
#
|
|
227
|
-
# @example Use as Enumerator
|
|
228
|
-
# names = ZLight.foreach("name,age\nAlice,30").map { |row| row[:name] }
|
|
229
|
-
# # => ["Alice"]
|
|
230
|
-
#
|
|
231
|
-
# @example Chain with Enumerable methods
|
|
232
|
-
# adults = ZLight.foreach(csv_data, converters: :numeric)
|
|
233
|
-
# .select { |row| row[:age] >= 18 }
|
|
234
|
-
# .map { |row| row[:name] }
|
|
111
|
+
# Note that unlike `CSV.foreach`, this takes a **string, not a path**, and
|
|
112
|
+
# parses the whole input before yielding. For lazy iteration use {.open}.
|
|
235
113
|
#
|
|
114
|
+
# @param csv_string [String] the CSV data
|
|
115
|
+
# @param options [Hash] any option accepted by {.parse}
|
|
116
|
+
# @yieldparam row [Hash, Array] each row in turn
|
|
117
|
+
# @return [nil, Enumerator] an Enumerator when no block is given
|
|
236
118
|
# @see .parse
|
|
237
|
-
def foreach(csv_string, **options, &
|
|
119
|
+
def foreach(csv_string, **options, &)
|
|
238
120
|
return to_enum(:foreach, csv_string, **options) unless block_given?
|
|
239
121
|
|
|
240
|
-
parse(csv_string, **options).each(&
|
|
122
|
+
parse(csv_string, **options).each(&)
|
|
241
123
|
end
|
|
242
124
|
|
|
243
|
-
#
|
|
244
|
-
#
|
|
245
|
-
#
|
|
246
|
-
#
|
|
247
|
-
#
|
|
248
|
-
#
|
|
249
|
-
#
|
|
250
|
-
#
|
|
251
|
-
# @
|
|
252
|
-
# @
|
|
253
|
-
#
|
|
254
|
-
# @
|
|
255
|
-
#
|
|
256
|
-
# @
|
|
257
|
-
#
|
|
258
|
-
#
|
|
259
|
-
# @yieldparam reader [ZLight::StreamReader] The streaming reader
|
|
260
|
-
#
|
|
261
|
-
# @return [ZLight::StreamReader] The streaming reader (if no block)
|
|
262
|
-
# @return [Object] The block's return value (if block given)
|
|
263
|
-
#
|
|
264
|
-
# @raise [Errno::ENOENT] If the file does not exist
|
|
265
|
-
# @raise [Errno::EACCES] If the file is not readable
|
|
266
|
-
#
|
|
267
|
-
# @example Process a large file row by row
|
|
268
|
-
# ZLight.open("users.csv") do |reader|
|
|
269
|
-
# reader.each do |row|
|
|
270
|
-
# User.create!(name: row[:name], email: row[:email])
|
|
271
|
-
# end
|
|
272
|
-
# end
|
|
273
|
-
#
|
|
274
|
-
# @example Get first 100 matching rows lazily
|
|
275
|
-
# ZLight.open("data.csv", converters: :numeric) do |reader|
|
|
276
|
-
# reader.lazy
|
|
277
|
-
# .select { |row| row[:score] > 90 }
|
|
278
|
-
# .first(100)
|
|
279
|
-
# end
|
|
280
|
-
#
|
|
281
|
-
# @example Manual resource management
|
|
282
|
-
# reader = ZLight.open("large.csv")
|
|
283
|
-
# begin
|
|
284
|
-
# reader.each { |row| process(row) }
|
|
285
|
-
# ensure
|
|
286
|
-
# reader.close
|
|
125
|
+
# Streams a CSV file, closing the reader afterwards.
|
|
126
|
+
#
|
|
127
|
+
# The memory-efficient way to process a large file: rows are read one at a
|
|
128
|
+
# time rather than materialised up front. With a block the reader is closed
|
|
129
|
+
# when the block exits, including on an exception.
|
|
130
|
+
#
|
|
131
|
+
# @param path [String] path to the CSV file
|
|
132
|
+
# @param options [Hash] any option accepted by {.parse}
|
|
133
|
+
# @yieldparam reader [ZLight::StreamReader] the reader
|
|
134
|
+
# @return [Object, ZLight::StreamReader] the block's value, or the reader
|
|
135
|
+
# itself when no block is given, in which case you must close it
|
|
136
|
+
# @raise [IOError] if the file does not exist or cannot be read
|
|
137
|
+
#
|
|
138
|
+
# @example Stop early without reading the rest of the file
|
|
139
|
+
# ZLight.open("huge.csv", converters: :numeric) do |reader|
|
|
140
|
+
# reader.lazy.select { |row| row[:score] > 90 }.first(100)
|
|
287
141
|
# end
|
|
288
142
|
#
|
|
289
143
|
# @see ZLight::StreamReader
|
|
290
144
|
def open(path, **options)
|
|
291
145
|
reader = stream_file(path, **options)
|
|
146
|
+
return reader unless block_given?
|
|
292
147
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
reader.close unless reader.closed?
|
|
298
|
-
end
|
|
299
|
-
else
|
|
300
|
-
reader
|
|
148
|
+
begin
|
|
149
|
+
yield reader
|
|
150
|
+
ensure
|
|
151
|
+
reader.close unless reader.closed?
|
|
301
152
|
end
|
|
302
153
|
end
|
|
303
154
|
end
|
|
155
|
+
|
|
156
|
+
# A single-pass reader over a CSV source, yielding one row at a time.
|
|
157
|
+
#
|
|
158
|
+
# Defined in the native extension; see ext/zlight_csv/src/read/stream.rs.
|
|
159
|
+
# Obtained from {ZLight.stream}, {ZLight.stream_file} or {ZLight.open}.
|
|
160
|
+
#
|
|
161
|
+
# Includes `Enumerable`, so `map`, `select`, `find` and `lazy` all work — but
|
|
162
|
+
# the reader is **single-pass**: each row is consumed as it is read, so a
|
|
163
|
+
# second enumeration yields nothing and there is no rewind.
|
|
164
|
+
#
|
|
165
|
+
# @!method next_row
|
|
166
|
+
# @return [Hash, Array, nil] the next row, or nil once exhausted
|
|
167
|
+
# @raise [ZLight::StreamClosedError] if the reader has been closed
|
|
168
|
+
# @!method each
|
|
169
|
+
# @yieldparam row [Hash, Array] each row in turn
|
|
170
|
+
# @return [self, Enumerator] an Enumerator when no block is given
|
|
171
|
+
# @!method headers
|
|
172
|
+
# @return [Array<Symbol>, nil] the header symbols, or nil without headers
|
|
173
|
+
# @!method close
|
|
174
|
+
# Releases the underlying file or buffer. Idempotent.
|
|
175
|
+
# @return [nil]
|
|
176
|
+
# @!method closed?
|
|
177
|
+
# @return [Boolean]
|
|
178
|
+
# @!method eof?
|
|
179
|
+
# @return [Boolean] true once exhausted or closed
|
|
180
|
+
# Reopened solely to attach the documentation above; the class itself and
|
|
181
|
+
# all of its methods come from the extension.
|
|
182
|
+
class StreamReader; end # rubocop:disable Lint/EmptyClass
|
|
304
183
|
end
|
metadata
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zlight_csv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- Zaidan Chaudhary
|
|
8
|
+
- Saad Chaudhary
|
|
8
9
|
autorequire:
|
|
9
10
|
bindir: bin
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
12
|
-
dependencies:
|
|
12
|
+
date: 2026-09-12 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: rb_sys
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - "~>"
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '0.9'
|
|
21
|
+
type: :runtime
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - "~>"
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '0.9'
|
|
13
28
|
description: |
|
|
14
29
|
ZLight brings the speed of Rust to Ruby's CSV parsing. Built as a native
|
|
15
|
-
extension, it delivers up to
|
|
30
|
+
extension, it delivers up to 40x faster performance than Ruby's standard
|
|
16
31
|
CSV library while maintaining full API compatibility. Whether you're parsing
|
|
17
32
|
small configuration files or processing millions of rows, ZLight handles it
|
|
18
33
|
efficiently. The streaming API enables memory-efficient processing of large
|
|
@@ -24,22 +39,36 @@ executables: []
|
|
|
24
39
|
extensions: []
|
|
25
40
|
extra_rdoc_files: []
|
|
26
41
|
files:
|
|
42
|
+
- ARCHITECTURE.md
|
|
27
43
|
- CHANGELOG.md
|
|
28
44
|
- LICENSE
|
|
29
45
|
- README.md
|
|
30
46
|
- VERSION
|
|
47
|
+
- ext/zlight_csv/Cargo.toml
|
|
48
|
+
- ext/zlight_csv/extconf.rb
|
|
49
|
+
- ext/zlight_csv/src/convert.rs
|
|
50
|
+
- ext/zlight_csv/src/error.rs
|
|
51
|
+
- ext/zlight_csv/src/lib.rs
|
|
52
|
+
- ext/zlight_csv/src/options.rs
|
|
53
|
+
- ext/zlight_csv/src/reader.rs
|
|
54
|
+
- ext/zlight_csv/src/row.rs
|
|
31
55
|
- lib/zlight_csv.rb
|
|
32
|
-
- lib/zlight_csv/3.0/zlight_csv.so
|
|
33
56
|
- lib/zlight_csv/3.1/zlight_csv.so
|
|
34
57
|
- lib/zlight_csv/3.2/zlight_csv.so
|
|
35
58
|
- lib/zlight_csv/3.3/zlight_csv.so
|
|
59
|
+
- lib/zlight_csv/3.4/zlight_csv.so
|
|
60
|
+
- lib/zlight_csv/4.0/zlight_csv.so
|
|
61
|
+
- lib/zlight_csv/errors.rb
|
|
62
|
+
- lib/zlight_csv/native.rb
|
|
36
63
|
- lib/zlight_csv/version.rb
|
|
37
|
-
homepage: https://
|
|
64
|
+
homepage: https://github.com/codebyisaad/zlight
|
|
38
65
|
licenses:
|
|
39
66
|
- MIT
|
|
40
67
|
metadata:
|
|
41
|
-
|
|
42
|
-
|
|
68
|
+
source_code_uri: https://github.com/codebyisaad/zlight
|
|
69
|
+
changelog_uri: https://github.com/codebyisaad/zlight/blob/main/CHANGELOG.md
|
|
70
|
+
bug_tracker_uri: https://github.com/codebyisaad/zlight/issues
|
|
71
|
+
documentation_uri: https://codebyisaad.github.io/zlight-docs/
|
|
43
72
|
rubygems_mfa_required: 'true'
|
|
44
73
|
post_install_message:
|
|
45
74
|
rdoc_options: []
|
|
@@ -49,10 +78,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
49
78
|
requirements:
|
|
50
79
|
- - ">="
|
|
51
80
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '3.
|
|
81
|
+
version: '3.1'
|
|
53
82
|
- - "<"
|
|
54
83
|
- !ruby/object:Gem::Version
|
|
55
|
-
version:
|
|
84
|
+
version: 4.1.dev
|
|
56
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
86
|
requirements:
|
|
58
87
|
- - ">="
|
|
Binary file
|