parquet 0.5.13 → 0.6.0

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +295 -98
  3. data/Cargo.toml +1 -1
  4. data/Gemfile +1 -0
  5. data/README.md +94 -3
  6. data/ext/parquet/Cargo.toml +3 -0
  7. data/ext/parquet/src/adapter_ffi.rs +156 -0
  8. data/ext/parquet/src/lib.rs +13 -21
  9. data/ext/parquet-core/Cargo.toml +23 -0
  10. data/ext/parquet-core/src/arrow_conversion.rs +1133 -0
  11. data/ext/parquet-core/src/error.rs +163 -0
  12. data/ext/parquet-core/src/lib.rs +60 -0
  13. data/ext/parquet-core/src/reader.rs +263 -0
  14. data/ext/parquet-core/src/schema.rs +283 -0
  15. data/ext/parquet-core/src/test_utils.rs +308 -0
  16. data/ext/parquet-core/src/traits/mod.rs +5 -0
  17. data/ext/parquet-core/src/traits/schema.rs +151 -0
  18. data/ext/parquet-core/src/value.rs +209 -0
  19. data/ext/parquet-core/src/writer.rs +839 -0
  20. data/ext/parquet-core/tests/arrow_conversion_tests.rs +423 -0
  21. data/ext/parquet-core/tests/binary_data.rs +437 -0
  22. data/ext/parquet-core/tests/column_projection.rs +557 -0
  23. data/ext/parquet-core/tests/complex_types.rs +821 -0
  24. data/ext/parquet-core/tests/compression_tests.rs +434 -0
  25. data/ext/parquet-core/tests/concurrent_access.rs +430 -0
  26. data/ext/parquet-core/tests/decimal_tests.rs +488 -0
  27. data/ext/parquet-core/tests/edge_cases_corner_cases.rs +322 -0
  28. data/ext/parquet-core/tests/error_handling_comprehensive_tests.rs +547 -0
  29. data/ext/parquet-core/tests/null_handling_tests.rs +430 -0
  30. data/ext/parquet-core/tests/performance_memory.rs +181 -0
  31. data/ext/parquet-core/tests/primitive_types.rs +547 -0
  32. data/ext/parquet-core/tests/real_world_patterns.rs +777 -0
  33. data/ext/parquet-core/tests/roundtrip_correctness.rs +279 -0
  34. data/ext/parquet-core/tests/schema_comprehensive_tests.rs +534 -0
  35. data/ext/parquet-core/tests/temporal_tests.rs +518 -0
  36. data/ext/parquet-core/tests/test_helpers.rs +132 -0
  37. data/ext/parquet-core/tests/writer_tests.rs +545 -0
  38. data/ext/parquet-ruby-adapter/Cargo.toml +22 -0
  39. data/ext/parquet-ruby-adapter/build.rs +5 -0
  40. data/ext/parquet-ruby-adapter/examples/try_into_value_demo.rs +98 -0
  41. data/ext/parquet-ruby-adapter/src/batch_manager.rs +116 -0
  42. data/ext/parquet-ruby-adapter/src/chunk_reader.rs +237 -0
  43. data/ext/parquet-ruby-adapter/src/converter.rs +1685 -0
  44. data/ext/parquet-ruby-adapter/src/error.rs +148 -0
  45. data/ext/{parquet/src/ruby_reader.rs → parquet-ruby-adapter/src/io.rs} +190 -56
  46. data/ext/parquet-ruby-adapter/src/lib.rs +90 -0
  47. data/ext/parquet-ruby-adapter/src/logger.rs +64 -0
  48. data/ext/parquet-ruby-adapter/src/metadata.rs +427 -0
  49. data/ext/parquet-ruby-adapter/src/reader.rs +317 -0
  50. data/ext/parquet-ruby-adapter/src/schema.rs +810 -0
  51. data/ext/parquet-ruby-adapter/src/string_cache.rs +106 -0
  52. data/ext/parquet-ruby-adapter/src/try_into_value.rs +91 -0
  53. data/ext/parquet-ruby-adapter/src/types.rs +94 -0
  54. data/ext/parquet-ruby-adapter/src/utils.rs +186 -0
  55. data/ext/parquet-ruby-adapter/src/writer.rs +435 -0
  56. data/lib/parquet/schema.rb +19 -0
  57. data/lib/parquet/version.rb +1 -1
  58. metadata +50 -24
  59. data/ext/parquet/src/enumerator.rs +0 -68
  60. data/ext/parquet/src/header_cache.rs +0 -99
  61. data/ext/parquet/src/logger.rs +0 -171
  62. data/ext/parquet/src/reader/common.rs +0 -111
  63. data/ext/parquet/src/reader/mod.rs +0 -211
  64. data/ext/parquet/src/reader/parquet_column_reader.rs +0 -44
  65. data/ext/parquet/src/reader/parquet_row_reader.rs +0 -43
  66. data/ext/parquet/src/reader/unified/mod.rs +0 -363
  67. data/ext/parquet/src/types/core_types.rs +0 -120
  68. data/ext/parquet/src/types/mod.rs +0 -100
  69. data/ext/parquet/src/types/parquet_value.rs +0 -1275
  70. data/ext/parquet/src/types/record_types.rs +0 -605
  71. data/ext/parquet/src/types/schema_converter.rs +0 -290
  72. data/ext/parquet/src/types/schema_node.rs +0 -424
  73. data/ext/parquet/src/types/timestamp.rs +0 -285
  74. data/ext/parquet/src/types/type_conversion.rs +0 -1949
  75. data/ext/parquet/src/types/writer_types.rs +0 -329
  76. data/ext/parquet/src/utils.rs +0 -184
  77. data/ext/parquet/src/writer/mod.rs +0 -505
  78. data/ext/parquet/src/writer/write_columns.rs +0 -238
  79. data/ext/parquet/src/writer/write_rows.rs +0 -488
@@ -0,0 +1,547 @@
1
+ use bytes::Bytes;
2
+ use ordered_float::OrderedFloat;
3
+ use parquet_core::*;
4
+ use std::sync::Arc;
5
+
6
+ // =============================================================================
7
+ // Boolean Type Tests
8
+ // =============================================================================
9
+
10
+ #[test]
11
+ fn test_boolean_values() {
12
+ let schema = SchemaBuilder::new()
13
+ .with_root(SchemaNode::Struct {
14
+ name: "root".to_string(),
15
+ nullable: false,
16
+ fields: vec![
17
+ SchemaNode::Primitive {
18
+ name: "bool_field".to_string(),
19
+ primitive_type: PrimitiveType::Boolean,
20
+ nullable: false,
21
+ format: None,
22
+ },
23
+ SchemaNode::Primitive {
24
+ name: "nullable_bool".to_string(),
25
+ primitive_type: PrimitiveType::Boolean,
26
+ nullable: true,
27
+ format: None,
28
+ },
29
+ ],
30
+ })
31
+ .build()
32
+ .unwrap();
33
+
34
+ let rows = vec![
35
+ vec![ParquetValue::Boolean(true), ParquetValue::Boolean(true)],
36
+ vec![ParquetValue::Boolean(false), ParquetValue::Boolean(false)],
37
+ vec![ParquetValue::Boolean(true), ParquetValue::Null],
38
+ vec![ParquetValue::Boolean(false), ParquetValue::Null],
39
+ // Many repeated values to test encoding efficiency
40
+ vec![ParquetValue::Boolean(true), ParquetValue::Boolean(true)],
41
+ vec![ParquetValue::Boolean(true), ParquetValue::Boolean(true)],
42
+ vec![ParquetValue::Boolean(true), ParquetValue::Boolean(true)],
43
+ vec![ParquetValue::Boolean(false), ParquetValue::Boolean(false)],
44
+ vec![ParquetValue::Boolean(false), ParquetValue::Boolean(false)],
45
+ ];
46
+
47
+ let mut buffer = Vec::new();
48
+ {
49
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
50
+ writer.write_rows(rows.clone()).unwrap();
51
+ writer.close().unwrap();
52
+ }
53
+
54
+ // Read back and verify
55
+ let bytes = Bytes::from(buffer);
56
+ let reader = Reader::new(bytes);
57
+
58
+ let read_rows: Vec<_> = reader
59
+ .read_rows()
60
+ .unwrap()
61
+ .collect::<Result<Vec<_>>>()
62
+ .unwrap();
63
+
64
+ assert_eq!(rows.len(), read_rows.len());
65
+ for (expected, actual) in rows.iter().zip(read_rows.iter()) {
66
+ assert_eq!(expected, actual);
67
+ }
68
+ }
69
+
70
+ #[test]
71
+ fn test_boolean_in_complex_types() {
72
+ let schema = SchemaBuilder::new()
73
+ .with_root(SchemaNode::Struct {
74
+ name: "root".to_string(),
75
+ nullable: false,
76
+ fields: vec![
77
+ SchemaNode::List {
78
+ name: "bool_list".to_string(),
79
+ nullable: false,
80
+ item: Box::new(SchemaNode::Primitive {
81
+ name: "item".to_string(),
82
+ primitive_type: PrimitiveType::Boolean,
83
+ nullable: false,
84
+ format: None,
85
+ }),
86
+ },
87
+ SchemaNode::Map {
88
+ name: "bool_map".to_string(),
89
+ nullable: false,
90
+ key: Box::new(SchemaNode::Primitive {
91
+ name: "key".to_string(),
92
+ primitive_type: PrimitiveType::String,
93
+ nullable: false,
94
+ format: None,
95
+ }),
96
+ value: Box::new(SchemaNode::Primitive {
97
+ name: "value".to_string(),
98
+ primitive_type: PrimitiveType::Boolean,
99
+ nullable: true,
100
+ format: None,
101
+ }),
102
+ },
103
+ ],
104
+ })
105
+ .build()
106
+ .unwrap();
107
+
108
+ let rows = vec![
109
+ vec![
110
+ ParquetValue::List(vec![
111
+ ParquetValue::Boolean(true),
112
+ ParquetValue::Boolean(false),
113
+ ParquetValue::Boolean(true),
114
+ ]),
115
+ ParquetValue::Map(vec![
116
+ (
117
+ ParquetValue::String(Arc::from("enabled")),
118
+ ParquetValue::Boolean(true),
119
+ ),
120
+ (
121
+ ParquetValue::String(Arc::from("disabled")),
122
+ ParquetValue::Boolean(false),
123
+ ),
124
+ (
125
+ ParquetValue::String(Arc::from("unknown")),
126
+ ParquetValue::Null,
127
+ ),
128
+ ]),
129
+ ],
130
+ vec![ParquetValue::List(vec![]), ParquetValue::Map(vec![])],
131
+ ];
132
+
133
+ let mut buffer = Vec::new();
134
+ {
135
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
136
+ writer.write_rows(rows.clone()).unwrap();
137
+ writer.close().unwrap();
138
+ }
139
+
140
+ // Read back and verify
141
+ let bytes = Bytes::from(buffer);
142
+ let reader = Reader::new(bytes);
143
+
144
+ let read_rows: Vec<_> = reader
145
+ .read_rows()
146
+ .unwrap()
147
+ .collect::<Result<Vec<_>>>()
148
+ .unwrap();
149
+
150
+ assert_eq!(rows.len(), read_rows.len());
151
+ for (expected, actual) in rows.iter().zip(read_rows.iter()) {
152
+ assert_eq!(expected, actual);
153
+ }
154
+ }
155
+
156
+ // =============================================================================
157
+ // String Type Tests
158
+ // =============================================================================
159
+
160
+ #[test]
161
+ fn test_string_roundtrip() {
162
+ let schema = SchemaBuilder::new()
163
+ .with_root(SchemaNode::Struct {
164
+ name: "root".to_string(),
165
+ nullable: false,
166
+ fields: vec![SchemaNode::Primitive {
167
+ name: "text".to_string(),
168
+ primitive_type: PrimitiveType::String,
169
+ nullable: false,
170
+ format: None,
171
+ }],
172
+ })
173
+ .build()
174
+ .unwrap();
175
+
176
+ let repeated_str = "Repeated".repeat(100);
177
+ let long_str = "x".repeat(10_000);
178
+
179
+ let test_strings = vec![
180
+ "", // Empty string
181
+ "Hello, World!", // ASCII
182
+ "Hello, 世界! 🦀", // Unicode with emoji
183
+ "Line1\nLine2\rLine3\r\nLine4", // Various line endings
184
+ "\t\t\tTabbed\t\t\t", // Tabs
185
+ "Special chars: !@#$%^&*()_+-=[]{}|;':\",./<>?",
186
+ repeated_str.as_str(), // Long repeated string
187
+ long_str.as_str(), // Very long string
188
+ ];
189
+
190
+ let rows: Vec<Vec<ParquetValue>> = test_strings
191
+ .into_iter()
192
+ .map(|s| vec![ParquetValue::String(Arc::from(s))])
193
+ .collect();
194
+
195
+ let mut buffer = Vec::new();
196
+ {
197
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
198
+ writer.write_rows(rows.clone()).unwrap();
199
+ writer.close().unwrap();
200
+ }
201
+
202
+ // Read back and verify
203
+ let bytes = Bytes::from(buffer);
204
+ let reader = Reader::new(bytes);
205
+
206
+ let read_rows: Vec<_> = reader
207
+ .read_rows()
208
+ .unwrap()
209
+ .collect::<Result<Vec<_>>>()
210
+ .unwrap();
211
+
212
+ assert_eq!(rows.len(), read_rows.len());
213
+ for (expected, actual) in rows.iter().zip(read_rows.iter()) {
214
+ assert_eq!(expected, actual);
215
+ }
216
+ }
217
+
218
+ // =============================================================================
219
+ // Numeric Type Tests
220
+ // =============================================================================
221
+
222
+ #[test]
223
+ fn test_float_special_values() {
224
+ // Test NaN, Infinity, and -Infinity handling
225
+ let schema = SchemaBuilder::new()
226
+ .with_root(SchemaNode::Struct {
227
+ name: "root".to_string(),
228
+ nullable: false,
229
+ fields: vec![
230
+ SchemaNode::Primitive {
231
+ name: "float32_val".to_string(),
232
+ primitive_type: PrimitiveType::Float32,
233
+ nullable: false,
234
+ format: None,
235
+ },
236
+ SchemaNode::Primitive {
237
+ name: "float64_val".to_string(),
238
+ primitive_type: PrimitiveType::Float64,
239
+ nullable: false,
240
+ format: None,
241
+ },
242
+ ],
243
+ })
244
+ .build()
245
+ .unwrap();
246
+
247
+ let special_values = vec![
248
+ // Normal values
249
+ vec![
250
+ ParquetValue::Float32(OrderedFloat(1.23f32)),
251
+ ParquetValue::Float64(OrderedFloat(4.56f64)),
252
+ ],
253
+ // Positive infinity
254
+ vec![
255
+ ParquetValue::Float32(OrderedFloat(f32::INFINITY)),
256
+ ParquetValue::Float64(OrderedFloat(f64::INFINITY)),
257
+ ],
258
+ // Negative infinity
259
+ vec![
260
+ ParquetValue::Float32(OrderedFloat(f32::NEG_INFINITY)),
261
+ ParquetValue::Float64(OrderedFloat(f64::NEG_INFINITY)),
262
+ ],
263
+ // NaN values
264
+ vec![
265
+ ParquetValue::Float32(OrderedFloat(f32::NAN)),
266
+ ParquetValue::Float64(OrderedFloat(f64::NAN)),
267
+ ],
268
+ // Zero values
269
+ vec![
270
+ ParquetValue::Float32(OrderedFloat(0.0f32)),
271
+ ParquetValue::Float64(OrderedFloat(0.0f64)),
272
+ ],
273
+ // Negative zero
274
+ vec![
275
+ ParquetValue::Float32(OrderedFloat(-0.0f32)),
276
+ ParquetValue::Float64(OrderedFloat(-0.0f64)),
277
+ ],
278
+ // Very small values
279
+ vec![
280
+ ParquetValue::Float32(OrderedFloat(f32::MIN_POSITIVE)),
281
+ ParquetValue::Float64(OrderedFloat(f64::MIN_POSITIVE)),
282
+ ],
283
+ // Very large values
284
+ vec![
285
+ ParquetValue::Float32(OrderedFloat(f32::MAX)),
286
+ ParquetValue::Float64(OrderedFloat(f64::MAX)),
287
+ ],
288
+ ];
289
+
290
+ let mut buffer = Vec::new();
291
+ {
292
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
293
+ writer.write_rows(special_values.clone()).unwrap();
294
+ writer.close().unwrap();
295
+ }
296
+
297
+ // Read back and verify
298
+ let bytes = Bytes::from(buffer);
299
+ let reader = Reader::new(bytes);
300
+
301
+ let read_rows: Vec<_> = reader
302
+ .read_rows()
303
+ .unwrap()
304
+ .collect::<Result<Vec<_>>>()
305
+ .unwrap();
306
+
307
+ assert_eq!(read_rows.len(), special_values.len());
308
+
309
+ // Verify special values are preserved
310
+ for (expected, actual) in special_values.iter().zip(read_rows.iter()) {
311
+ for (exp_val, act_val) in expected.iter().zip(actual.iter()) {
312
+ match (exp_val, act_val) {
313
+ (
314
+ ParquetValue::Float32(OrderedFloat(e)),
315
+ ParquetValue::Float32(OrderedFloat(a)),
316
+ ) => {
317
+ if e.is_nan() {
318
+ assert!(a.is_nan());
319
+ } else {
320
+ assert_eq!(e, a);
321
+ }
322
+ }
323
+ (
324
+ ParquetValue::Float64(OrderedFloat(e)),
325
+ ParquetValue::Float64(OrderedFloat(a)),
326
+ ) => {
327
+ if e.is_nan() {
328
+ assert!(a.is_nan());
329
+ } else {
330
+ assert_eq!(e, a);
331
+ }
332
+ }
333
+ _ => panic!("Type mismatch"),
334
+ }
335
+ }
336
+ }
337
+ }
338
+
339
+ // Macro to generate integer boundary tests for each type
340
+ macro_rules! test_integer_boundaries {
341
+ ($test_name:ident, $type_name:expr, $primitive_type:expr, $rust_type:ty, $parquet_variant:ident, $test_values:expr) => {
342
+ #[test]
343
+ fn $test_name() {
344
+ let schema = SchemaBuilder::new()
345
+ .with_root(SchemaNode::Struct {
346
+ name: "root".to_string(),
347
+ nullable: false,
348
+ fields: vec![SchemaNode::Primitive {
349
+ name: $type_name.to_string(),
350
+ primitive_type: $primitive_type,
351
+ nullable: false,
352
+ format: None,
353
+ }],
354
+ })
355
+ .build()
356
+ .unwrap();
357
+
358
+ let boundary_values: Vec<Vec<ParquetValue>> = $test_values
359
+ .into_iter()
360
+ .map(|v| vec![ParquetValue::$parquet_variant(v)])
361
+ .collect();
362
+
363
+ let mut buffer = Vec::new();
364
+ {
365
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
366
+ writer.write_rows(boundary_values.clone()).unwrap();
367
+ writer.close().unwrap();
368
+ }
369
+
370
+ // Read back and verify
371
+ let bytes = Bytes::from(buffer);
372
+ let reader = Reader::new(bytes);
373
+
374
+ let read_rows: Vec<_> = reader
375
+ .read_rows()
376
+ .unwrap()
377
+ .collect::<Result<Vec<_>>>()
378
+ .unwrap();
379
+
380
+ assert_eq!(read_rows.len(), boundary_values.len());
381
+ for (expected, actual) in boundary_values.iter().zip(read_rows.iter()) {
382
+ assert_eq!(expected, actual);
383
+ }
384
+ }
385
+ };
386
+ }
387
+
388
+ // Generate tests for all integer types
389
+ test_integer_boundaries!(
390
+ test_int8_boundaries,
391
+ "int8",
392
+ PrimitiveType::Int8,
393
+ i8,
394
+ Int8,
395
+ vec![i8::MIN, i8::MAX, 0, -1, 42, -42]
396
+ );
397
+
398
+ test_integer_boundaries!(
399
+ test_int16_boundaries,
400
+ "int16",
401
+ PrimitiveType::Int16,
402
+ i16,
403
+ Int16,
404
+ vec![i16::MIN, i16::MAX, 0, -1, 1000, -1000]
405
+ );
406
+
407
+ test_integer_boundaries!(
408
+ test_int32_boundaries,
409
+ "int32",
410
+ PrimitiveType::Int32,
411
+ i32,
412
+ Int32,
413
+ vec![i32::MIN, i32::MAX, 0, -1, 1_000_000, -1_000_000]
414
+ );
415
+
416
+ test_integer_boundaries!(
417
+ test_int64_boundaries,
418
+ "int64",
419
+ PrimitiveType::Int64,
420
+ i64,
421
+ Int64,
422
+ vec![
423
+ i64::MIN,
424
+ i64::MAX,
425
+ 0,
426
+ -1,
427
+ 1_000_000_000_000,
428
+ -1_000_000_000_000
429
+ ]
430
+ );
431
+
432
+ test_integer_boundaries!(
433
+ test_uint8_boundaries,
434
+ "uint8",
435
+ PrimitiveType::UInt8,
436
+ u8,
437
+ UInt8,
438
+ vec![u8::MIN, u8::MAX, 0, 1, 128, 255]
439
+ );
440
+
441
+ test_integer_boundaries!(
442
+ test_uint16_boundaries,
443
+ "uint16",
444
+ PrimitiveType::UInt16,
445
+ u16,
446
+ UInt16,
447
+ vec![u16::MIN, u16::MAX, 0, 1, 32768, 65535]
448
+ );
449
+
450
+ test_integer_boundaries!(
451
+ test_uint32_boundaries,
452
+ "uint32",
453
+ PrimitiveType::UInt32,
454
+ u32,
455
+ UInt32,
456
+ vec![u32::MIN, u32::MAX, 0, 1, 2_147_483_648, 4_294_967_295]
457
+ );
458
+
459
+ test_integer_boundaries!(
460
+ test_uint64_boundaries,
461
+ "uint64",
462
+ PrimitiveType::UInt64,
463
+ u64,
464
+ UInt64,
465
+ vec![
466
+ u64::MIN,
467
+ u64::MAX,
468
+ 0,
469
+ 1,
470
+ 9_223_372_036_854_775_808,
471
+ 18_446_744_073_709_551_615
472
+ ]
473
+ );
474
+
475
+ #[test]
476
+ fn test_mixed_numeric_types() {
477
+ // Test writing different numeric types and reading them back
478
+ let schema = SchemaBuilder::new()
479
+ .with_root(SchemaNode::Struct {
480
+ name: "root".to_string(),
481
+ nullable: false,
482
+ fields: vec![
483
+ SchemaNode::Primitive {
484
+ name: "as_int8".to_string(),
485
+ primitive_type: PrimitiveType::Int8,
486
+ nullable: false,
487
+ format: None,
488
+ },
489
+ SchemaNode::Primitive {
490
+ name: "as_int32".to_string(),
491
+ primitive_type: PrimitiveType::Int32,
492
+ nullable: false,
493
+ format: None,
494
+ },
495
+ SchemaNode::Primitive {
496
+ name: "as_float".to_string(),
497
+ primitive_type: PrimitiveType::Float32,
498
+ nullable: false,
499
+ format: None,
500
+ },
501
+ ],
502
+ })
503
+ .build()
504
+ .unwrap();
505
+
506
+ // Test values that fit in all types
507
+ let test_values = vec![
508
+ vec![
509
+ ParquetValue::Int8(42),
510
+ ParquetValue::Int32(42),
511
+ ParquetValue::Float32(OrderedFloat(42.0)),
512
+ ],
513
+ vec![
514
+ ParquetValue::Int8(-50),
515
+ ParquetValue::Int32(-50),
516
+ ParquetValue::Float32(OrderedFloat(-50.0)),
517
+ ],
518
+ vec![
519
+ ParquetValue::Int8(0),
520
+ ParquetValue::Int32(0),
521
+ ParquetValue::Float32(OrderedFloat(0.0)),
522
+ ],
523
+ ];
524
+
525
+ let mut buffer = Vec::new();
526
+ {
527
+ let mut writer = Writer::new(&mut buffer, schema).unwrap();
528
+ writer.write_rows(test_values.clone()).unwrap();
529
+ writer.close().unwrap();
530
+ }
531
+
532
+ // Read back and verify
533
+ let bytes = Bytes::from(buffer);
534
+ let reader = Reader::new(bytes);
535
+
536
+ let read_rows: Vec<_> = reader
537
+ .read_rows()
538
+ .unwrap()
539
+ .collect::<Result<Vec<_>>>()
540
+ .unwrap();
541
+
542
+ assert_eq!(read_rows.len(), test_values.len());
543
+
544
+ for (expected, actual) in test_values.iter().zip(read_rows.iter()) {
545
+ assert_eq!(expected, actual);
546
+ }
547
+ }