Skip to content

Commit

Permalink
fix(io/bufio): fix handling of trailing new line (#990)
Browse files Browse the repository at this point in the history
  • Loading branch information
kt3k authored Jul 1, 2021
1 parent f3828fa commit 01af5fa
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
27 changes: 19 additions & 8 deletions io/bufio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
type Reader = Deno.Reader;
type Writer = Deno.Writer;
type WriterSync = Deno.WriterSync;
import { copy } from "../bytes/mod.ts";
import { concat, copy } from "../bytes/mod.ts";
import { assert } from "../_util/assert.ts";
import { BytesList } from "../bytes/bytes_list.ts";
import { writeAll, writeAllSync } from "./util.ts";
Expand Down Expand Up @@ -252,6 +252,9 @@ export class BufReader implements Reader {
try {
line = await this.readSlice(LF);
} catch (err) {
if (err instanceof Deno.errors.BadResource) {
throw err;
}
let { partial } = err;
assert(
partial instanceof Uint8Array,
Expand Down Expand Up @@ -707,13 +710,21 @@ export async function* readLines(
ignoreBOM?: boolean;
},
): AsyncIterableIterator<string> {
for await (let chunk of readStringDelim(reader, "\n", decoderOpts)) {
// Finding a CR at the end of the line is evidence of a
// "\r\n" at the end of the line. The "\r" part should be
// removed too.
if (chunk.endsWith("\r")) {
chunk = chunk.slice(0, -1);
const bufReader = new BufReader(reader);
let chunks: Uint8Array[] = [];
const decoder = new TextDecoder(decoderOpts?.encoding, decoderOpts);
while (true) {
const res = await bufReader.readLine();
if (!res) {
if (chunks.length > 0) {
yield decoder.decode(concat(...chunks));
}
break;
}
chunks.push(res.line);
if (!res.more) {
yield decoder.decode(concat(...chunks));
chunks = [];
}
yield chunk;
}
}
28 changes: 25 additions & 3 deletions io/bufio_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import { assert, assertEquals, fail } from "../testing/asserts.ts";
import {
assert,
assertEquals,
assertThrowsAsync,
fail,
} from "../testing/asserts.ts";
import {
BufferFullError,
BufReader,
Expand Down Expand Up @@ -242,6 +247,15 @@ Deno.test("bufioReadLine", async function () {
await testReadLine(testInputrn);
});

Deno.test("bufioReadLineBadResource", async () => {
const file = await Deno.open("README.md");
const bufReader = new BufReader(file);
file.close();
assertThrowsAsync(async () => {
await bufReader.readLine();
}, Deno.errors.BadResource);
});

Deno.test("[io] readStringDelim basic", async () => {
const delim = "!#$%&()=~";
const exp = [
Expand Down Expand Up @@ -480,6 +494,7 @@ Deno.test("readStringDelimAndLines", async function () {
assertEquals(chunks_, ["Hello World", "Hello World 2", "Hello World 3"]);

const linesData = new Buffer(enc.encode("0\n1\n2\n3\n4\n5\n6\n7\n8\n9"));
const linesDataWithTrailingNewLine = new Buffer(enc.encode("1\n2\n3\n"));
// consider data with windows newlines too
const linesDataWindows = new Buffer(
enc.encode("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9"),
Expand All @@ -493,6 +508,14 @@ Deno.test("readStringDelimAndLines", async function () {
assertEquals(lines_.length, 10);
assertEquals(lines_, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]);

lines_.length = 0;
for await (const l of readLines(linesDataWithTrailingNewLine)) {
lines_.push(l);
}

assertEquals(lines_.length, 3);
assertEquals(lines_, ["1", "2", "3"]); // No empty line at the end

// Now test for "windows" lines
lines_.length = 0;
for await (const l of readLines(linesDataWindows)) {
Expand All @@ -512,7 +535,7 @@ Deno.test("readLinesWithEncodingISO-8859-15", async function () {

Deno.close(file_.rid);

assertEquals(lines_.length, 13);
assertEquals(lines_.length, 12);
assertEquals(lines_, [
"\u0020!\"#$%&'()*+,-./",
"0123456789:;<=>?",
Expand All @@ -526,7 +549,6 @@ Deno.test("readLinesWithEncodingISO-8859-15", async function () {
"ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß",
"àáâãäåæçèéêëìíîï",
"ðñòóôõö÷øùúûüýþÿ",
"",
]);
});

Expand Down

0 comments on commit 01af5fa

Please sign in to comment.