Skip to content

Commit 5860a14

Browse files
committed
Improve parsing performance
1 parent 55ff729 commit 5860a14

3 files changed

Lines changed: 180 additions & 158 deletions

File tree

src/index.bench.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { describe, bench } from "vitest";
2+
import { parse, combineRanges } from "./index";
3+
4+
describe("parse", () => {
5+
bench("1000 byte range", () => {
6+
parse(1000, "bytes=0-499");
7+
});
8+
9+
bench("multiple byte ranges", () => {
10+
parse(1000, "bytes=0-99,200-299,400-499,600-699,800-899");
11+
});
12+
});
13+
14+
describe("combineRanges", () => {
15+
bench("simple overlapping ranges", () => {
16+
combineRanges([
17+
{
18+
start: 0,
19+
end: 499,
20+
},
21+
{ start: 400, end: 999 },
22+
]);
23+
});
24+
25+
bench("complex overlapping ranges", () => {
26+
combineRanges([
27+
{ start: 0, end: 199 },
28+
{ start: 150, end: 349 },
29+
{ start: 300, end: 499 },
30+
{ start: 400, end: 699 },
31+
{ start: 600, end: 999 },
32+
]);
33+
});
34+
});

src/index.spec.ts

Lines changed: 86 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import { describe, it, assert } from "vitest";
2-
import parse from "./index";
3-
4-
describe("parseRange(len, str)", function () {
5-
it("should reject non-string str", function () {
6-
assert.throws(
7-
parse.bind(null, 200, {} as any),
8-
/argument str must be a string/,
9-
);
10-
});
2+
import { parse, combineRanges } from "./index";
113

4+
describe("parse(len, str)", function () {
125
it("should return -2 for invalid str", function () {
136
assert.strictEqual(parse(200, "malformed"), -2);
147
});
@@ -57,125 +50,135 @@ describe("parseRange(len, str)", function () {
5750

5851
it("should parse str", function () {
5952
var range = parse(1000, "bytes=0-499");
60-
assert.deepEqual(
61-
range,
62-
Object.assign([{ start: 0, end: 499 }], { type: "bytes" }),
63-
);
53+
assert.deepEqual(range, {
54+
type: "bytes",
55+
ranges: [{ start: 0, end: 499 }],
56+
});
6457
});
6558

6659
it("should cap end at size", function () {
6760
var range = parse(200, "bytes=0-499");
68-
assert.deepEqual(
69-
range,
70-
Object.assign([{ start: 0, end: 199 }], { type: "bytes" }),
71-
);
61+
assert.deepEqual(range, {
62+
type: "bytes",
63+
ranges: [{ start: 0, end: 199 }],
64+
});
7265
});
7366

7467
it("should parse str", function () {
7568
var range = parse(1000, "bytes=40-80");
76-
assert.deepEqual(
77-
range,
78-
Object.assign([{ start: 40, end: 80 }], { type: "bytes" }),
79-
);
69+
assert.deepEqual(range, {
70+
type: "bytes",
71+
ranges: [{ start: 40, end: 80 }],
72+
});
8073
});
8174

8275
it("should parse str asking for last n bytes", function () {
8376
var range = parse(1000, "bytes=-400");
84-
assert.deepEqual(
85-
range,
86-
Object.assign([{ start: 600, end: 999 }], { type: "bytes" }),
87-
);
77+
assert.deepEqual(range, {
78+
type: "bytes",
79+
ranges: [{ start: 600, end: 999 }],
80+
});
8881
});
8982

9083
it("should parse str with only start", function () {
9184
var range = parse(1000, "bytes=400-");
92-
assert.deepEqual(
93-
range,
94-
Object.assign([{ start: 400, end: 999 }], { type: "bytes" }),
95-
);
85+
assert.deepEqual(range, {
86+
type: "bytes",
87+
ranges: [{ start: 400, end: 999 }],
88+
});
9689
});
9790

9891
it('should parse "bytes=0-"', function () {
9992
var range = parse(1000, "bytes=0-");
100-
assert.deepEqual(
101-
range,
102-
Object.assign([{ start: 0, end: 999 }], { type: "bytes" }),
103-
);
93+
assert.deepEqual(range, {
94+
type: "bytes",
95+
ranges: [{ start: 0, end: 999 }],
96+
});
10497
});
10598

10699
it("should parse str with no bytes", function () {
107100
var range = parse(1000, "bytes=0-0");
108-
assert.deepEqual(
109-
range,
110-
Object.assign([{ start: 0, end: 0 }], { type: "bytes" }),
111-
);
101+
assert.deepEqual(range, {
102+
type: "bytes",
103+
ranges: [{ start: 0, end: 0 }],
104+
});
112105
});
113106

114107
it("should parse str asking for last byte", function () {
115108
var range = parse(1000, "bytes=-1");
116-
assert.deepEqual(
117-
range,
118-
Object.assign([{ start: 999, end: 999 }], { type: "bytes" }),
119-
);
109+
assert.deepEqual(range, {
110+
type: "bytes",
111+
ranges: [{ start: 999, end: 999 }],
112+
});
120113
});
121114

122115
it("should parse str with multiple ranges", function () {
123116
var range = parse(1000, "bytes=40-80,81-90,-1");
124-
assert.deepEqual(
125-
range,
126-
Object.assign(
127-
[
128-
{ start: 40, end: 80 },
129-
{ start: 81, end: 90 },
130-
{ start: 999, end: 999 },
131-
],
132-
{ type: "bytes" },
133-
),
134-
);
117+
assert.deepEqual(range, {
118+
type: "bytes",
119+
ranges: [
120+
{ start: 40, end: 80 },
121+
{ start: 81, end: 90 },
122+
{ start: 999, end: 999 },
123+
],
124+
});
135125
});
136126

137127
it("should parse str with some invalid ranges", function () {
138128
var range = parse(200, "bytes=0-499,1000-,500-999");
139-
assert.deepEqual(
140-
range,
141-
Object.assign([{ start: 0, end: 199 }], { type: "bytes" }),
142-
);
129+
assert.deepEqual(range, {
130+
type: "bytes",
131+
ranges: [{ start: 0, end: 199 }],
132+
});
143133
});
144134

145135
it("should parse str with whitespace", function () {
146136
var range = parse(1000, "bytes= 40-80 , 81-90 , -1 ");
147-
assert.deepEqual(
148-
range,
149-
Object.assign(
150-
[
151-
{ start: 40, end: 80 },
152-
{ start: 81, end: 90 },
153-
{ start: 999, end: 999 },
154-
],
155-
{ type: "bytes" },
156-
),
157-
);
137+
assert.deepEqual(range, {
138+
type: "bytes",
139+
ranges: [
140+
{ start: 40, end: 80 },
141+
{ start: 81, end: 90 },
142+
{ start: 999, end: 999 },
143+
],
144+
});
158145
});
159146

160147
it("should parse non-byte range", function () {
161148
var range = parse(1000, "items=0-5");
162-
assert.deepEqual(
163-
range,
164-
Object.assign([{ start: 0, end: 5 }], { type: "items" }),
165-
);
166-
});
167-
168-
describe("when combine: true", function () {
169-
it("should combine overlapping ranges", function () {
170-
var range = parse(150, "bytes=0-4,90-99,5-75,100-199,101-102", {
171-
combine: true,
172-
});
173-
assert.deepEqual(range, parse(150, "bytes=0-75,90-149"));
149+
assert.deepEqual(range, {
150+
type: "items",
151+
ranges: [{ start: 0, end: 5 }],
174152
});
153+
});
154+
});
175155

176-
it("should retain original order", function () {
177-
var range = parse(150, "bytes=-1,20-100,0-1,101-120", { combine: true });
178-
assert.deepEqual(range, parse(150, "bytes=149-149,20-120,0-1"));
179-
});
156+
describe("combineRanges(ranges)", function () {
157+
it("should combine overlapping ranges", function () {
158+
var combined = combineRanges([
159+
{ start: 0, end: 4 },
160+
{ start: 90, end: 99 },
161+
{ start: 5, end: 75 },
162+
{ start: 100, end: 199 },
163+
{ start: 101, end: 102 },
164+
]);
165+
assert.deepEqual(combined, [
166+
{ start: 0, end: 75 },
167+
{ start: 90, end: 199 },
168+
]);
169+
});
170+
171+
it("should retain original order", function () {
172+
var combined = combineRanges([
173+
{ start: 149, end: 149 },
174+
{ start: 20, end: 100 },
175+
{ start: 0, end: 1 },
176+
{ start: 101, end: 120 },
177+
]);
178+
assert.deepEqual(combined, [
179+
{ start: 149, end: 149 },
180+
{ start: 20, end: 120 },
181+
{ start: 0, end: 1 },
182+
]);
180183
});
181184
});

0 commit comments

Comments
 (0)