Skip to content

Commit c686a82

Browse files
committed
Improve parsing performance
1 parent 55ff729 commit c686a82

3 files changed

Lines changed: 174 additions & 116 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: 80 additions & 41 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
});
@@ -59,123 +52,169 @@ describe("parseRange(len, str)", function () {
5952
var range = parse(1000, "bytes=0-499");
6053
assert.deepEqual(
6154
range,
62-
Object.assign([{ start: 0, end: 499 }], { type: "bytes" }),
55+
{
56+
type: "bytes",
57+
ranges: [{ start: 0, end: 499 }],
58+
},
6359
);
6460
});
6561

6662
it("should cap end at size", function () {
6763
var range = parse(200, "bytes=0-499");
6864
assert.deepEqual(
6965
range,
70-
Object.assign([{ start: 0, end: 199 }], { type: "bytes" }),
66+
{
67+
type: "bytes",
68+
ranges: [{ start: 0, end: 199 }],
69+
}
7170
);
7271
});
7372

7473
it("should parse str", function () {
7574
var range = parse(1000, "bytes=40-80");
7675
assert.deepEqual(
7776
range,
78-
Object.assign([{ start: 40, end: 80 }], { type: "bytes" }),
77+
{
78+
type: "bytes",
79+
ranges: [{ start: 40, end: 80 }],
80+
}
7981
);
8082
});
8183

8284
it("should parse str asking for last n bytes", function () {
8385
var range = parse(1000, "bytes=-400");
8486
assert.deepEqual(
8587
range,
86-
Object.assign([{ start: 600, end: 999 }], { type: "bytes" }),
88+
{
89+
type: "bytes",
90+
ranges: [{ start: 600, end: 999 }],
91+
}
8792
);
8893
});
8994

9095
it("should parse str with only start", function () {
9196
var range = parse(1000, "bytes=400-");
9297
assert.deepEqual(
9398
range,
94-
Object.assign([{ start: 400, end: 999 }], { type: "bytes" }),
99+
{
100+
type: "bytes",
101+
ranges: [{ start: 400, end: 999 }],
102+
}
95103
);
96104
});
97105

98106
it('should parse "bytes=0-"', function () {
99107
var range = parse(1000, "bytes=0-");
100108
assert.deepEqual(
101109
range,
102-
Object.assign([{ start: 0, end: 999 }], { type: "bytes" }),
110+
{
111+
type: "bytes",
112+
ranges: [{ start: 0, end: 999 }],
113+
}
103114
);
104115
});
105116

106117
it("should parse str with no bytes", function () {
107118
var range = parse(1000, "bytes=0-0");
108119
assert.deepEqual(
109120
range,
110-
Object.assign([{ start: 0, end: 0 }], { type: "bytes" }),
121+
{
122+
type: "bytes",
123+
ranges: [{ start: 0, end: 0 }],
124+
}
111125
);
112126
});
113127

114128
it("should parse str asking for last byte", function () {
115129
var range = parse(1000, "bytes=-1");
116130
assert.deepEqual(
117131
range,
118-
Object.assign([{ start: 999, end: 999 }], { type: "bytes" }),
132+
{
133+
type: "bytes",
134+
ranges: [{ start: 999, end: 999 }],
135+
}
119136
);
120137
});
121138

122139
it("should parse str with multiple ranges", function () {
123140
var range = parse(1000, "bytes=40-80,81-90,-1");
124141
assert.deepEqual(
125142
range,
126-
Object.assign(
127-
[
143+
{
144+
type: "bytes",
145+
ranges: [
128146
{ start: 40, end: 80 },
129147
{ start: 81, end: 90 },
130148
{ start: 999, end: 999 },
131149
],
132-
{ type: "bytes" },
133-
),
150+
}
134151
);
135152
});
136153

137154
it("should parse str with some invalid ranges", function () {
138155
var range = parse(200, "bytes=0-499,1000-,500-999");
139156
assert.deepEqual(
140157
range,
141-
Object.assign([{ start: 0, end: 199 }], { type: "bytes" }),
158+
{
159+
type: "bytes",
160+
ranges: [{ start: 0, end: 199 }],
161+
}
142162
);
143163
});
144164

145165
it("should parse str with whitespace", function () {
146166
var range = parse(1000, "bytes= 40-80 , 81-90 , -1 ");
147167
assert.deepEqual(
148168
range,
149-
Object.assign(
150-
[
169+
{
170+
type: "bytes",
171+
ranges: [
151172
{ start: 40, end: 80 },
152173
{ start: 81, end: 90 },
153174
{ start: 999, end: 999 },
154175
],
155-
{ type: "bytes" },
156-
),
176+
}
157177
);
158178
});
159179

160180
it("should parse non-byte range", function () {
161181
var range = parse(1000, "items=0-5");
162182
assert.deepEqual(
163183
range,
164-
Object.assign([{ start: 0, end: 5 }], { type: "items" }),
184+
{
185+
type: "items",
186+
ranges: [{ start: 0, end: 5 }],
187+
},
165188
);
166189
});
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"));
174-
});
175-
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-
});
180-
});
181190
});
191+
192+
describe("combineRanges(ranges)", function () {
193+
it("should combine overlapping ranges", function () {
194+
var combined = combineRanges([
195+
{ start: 0, end: 4 },
196+
{ start: 90, end: 99 },
197+
{ start: 5, end: 75 },
198+
{ start: 100, end: 199 },
199+
{ start: 101, end: 102 },
200+
]);
201+
assert.deepEqual(combined, [
202+
{ start: 0, end: 75 },
203+
{ start: 90, end: 199 },
204+
]);
205+
});
206+
207+
it("should retain original order", function () {
208+
var combined = combineRanges([
209+
{ start: 149, end: 149 },
210+
{ start: 20, end: 100 },
211+
{ start: 0, end: 1 },
212+
{ start: 101, end: 120 },
213+
]);
214+
assert.deepEqual(combined, [
215+
{ start: 149, end: 149 },
216+
{ start: 20, end: 120 },
217+
{ start: 0, end: 1 },
218+
]);
219+
});
220+
});

0 commit comments

Comments
 (0)