Skip to content

Commit

Permalink
readCSV: ignore trailing empty lines
Browse files Browse the repository at this point in the history
  • Loading branch information
vslinko committed May 15, 2024
1 parent 410f9e0 commit 2fb5cc0
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
16 changes: 15 additions & 1 deletion reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -709,10 +709,12 @@ export function readCSVRows(

class RowIterator implements AsyncIterableIterator<string> {
private onRequested: () => Promise<IteratorResult<string | symbol>>;
private buffer: Array<IteratorResult<string | symbol>>;
private done: boolean;

constructor(onRequested: () => Promise<IteratorResult<string | symbol>>) {
this.onRequested = onRequested;
this.buffer = [];
this.done = false;
}

Expand All @@ -726,12 +728,20 @@ class RowIterator implements AsyncIterableIterator<string> {
}
}

async lookForward(): Promise<IteratorResult<string | symbol>> {
const res = await this.onRequested();
this.buffer.push(res);
return res;
}

async next(): Promise<IteratorResult<string>> {
if (this.done) {
return { done: true, value: null };
}

const { done, value } = await this.onRequested();
const { done, value } = this.buffer.length > 0
? this.buffer.shift() as IteratorResult<string | symbol>
: await this.onRequested();

if (done || value === newLine) {
this.done = true;
Expand Down Expand Up @@ -842,6 +852,10 @@ class CSVRowIteratorReader implements AsyncIterableIterator<RowIterator> {
}

this.rowIterator = new RowIterator(() => this.onRequested());
const nextCell = await this.rowIterator.lookForward();
if (this.done && nextCell.done) {
return { done: true, value: undefined };
}

return { done: false, value: this.rowIterator };
}
Expand Down
55 changes: 55 additions & 0 deletions reader_test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { concat } from "./deps.ts";
import { assertEquals, assertRejects } from "./dev_deps.ts";
import {
newLine,
readCSV,
readCSVObjects,
readCSVRows,
Expand Down Expand Up @@ -262,6 +263,25 @@ Deno.test({
},
});

Deno.test({
name: "readCSV ignores trailing empty lines",
async fn() {
const reader = new MyReader(`1,2,3
a,b,c
`);

const rows = await asyncArrayFrom2(readCSV(reader));

assertEquals(rows, [
["1", "2", "3"],
["a", "b", "c"],
]);
},
});

Deno.test({
name: "readCSVStream couldn't be used twice",
async fn() {
Expand All @@ -283,6 +303,22 @@ Deno.test({
},
});

Deno.test({
name: "readCSVStream ignores trailing empty lines",
async fn() {
const reader = new MyReader(`1,2,3
a,b,c
`);

const rows = await asyncArrayFrom(readCSVStream(reader));

assertEquals(rows, ["1", "2", "3", newLine, "a", "b", "c", newLine]);
},
});

Deno.test({
name: "readCSVRows couldn't be used twice",
async fn() {
Expand Down Expand Up @@ -440,3 +476,22 @@ d,e,f`,
]);
},
});

Deno.test({
name: "readCSVRows ignores trailing empty lines",
async fn() {
const reader = new MyReader(`1,2,3
a,b,c
`);

const rows = await asyncArrayFrom(readCSVRows(reader));

assertEquals(rows, [
["1", "2", "3"],
["a", "b", "c"],
]);
},
});

0 comments on commit 2fb5cc0

Please sign in to comment.