Skip to content

Commit 6f22c49

Browse files
committed
feat(stringify): add serialization function for accept-ranges header field
1 parent 0c8b01c commit 6f22c49

File tree

8 files changed

+139
-2
lines changed

8 files changed

+139
-2
lines changed

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ assertEquals(parseAcceptRanges(`bytes, unknown`), ["bytes", "unknown"]);
2929
### Throwing error
3030

3131
Throws `SyntaxError` if the input is invalid
32-
[`<Accept-Ranges>`](https://www.rfc-editor.org/rfc/rfc9110#section-14.3-2).
32+
[`<Accept-Ranges>`](https://www.rfc-editor.org/rfc/rfc9110#section-14.3-2)
33+
syntax.
3334

3435
```ts
3536
import { parseAcceptRanges } from "https://deno.land/x/accept_ranges_parser@$VERSION/parse.ts";
@@ -38,6 +39,29 @@ import { assertThrows } from "https://deno.land/std/testing/asserts.ts";
3839
assertThrows(() => parseAcceptRanges("<invalid>"));
3940
```
4041

42+
## Serialization
43+
44+
Serialize string of array into string.
45+
46+
```ts
47+
import { stringifyAcceptRanges } from "https://deno.land/x/accept_ranges_parser@$VERSION/stringify.ts";
48+
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
49+
50+
assertEquals(stringifyAcceptRanges(["bytes"]), "bytes");
51+
```
52+
53+
### Throwing error
54+
55+
Throws `TypeError` if the element contains invalid
56+
[`<range-unit>`](https://www.rfc-editor.org/rfc/rfc9110#section-14.1-3) syntax.
57+
58+
```ts
59+
import { stringifyAcceptRanges } from "https://deno.land/x/accept_ranges_parser@$VERSION/stringify.ts";
60+
import { assertThrows } from "https://deno.land/std/testing/asserts.ts";
61+
62+
assertThrows(() => stringifyAcceptRanges(["<invalid>", "none"]));
63+
```
64+
4165
## AcceptRanges
4266

4367
`AcceptRanges` is a subtype of array with the following characteristics.

_tools/meta.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ export const makeOptions = (version: string): BuildOptions => ({
3636
publishConfig: { access: "public" },
3737
},
3838
packageManager: "pnpm",
39+
mappings: {
40+
"https://deno.land/x/[email protected]/is_string.ts": {
41+
name: "@miyauci/isx",
42+
version: "1.1.0",
43+
subPath: "is_string",
44+
},
45+
},
3946
});

constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33

44
export const enum Msg {
55
InvalidSyntax = "invalid <Accept-Ranges> syntax.",
6+
InvalidRangeUnit = "invalid <range-unit> syntax.",
67
}

deno.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deps.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2023-latest the httpland authors. All rights reserved. MIT license.
22
// This module is browser compatible.
33

4+
export { isString } from "https://deno.land/x/[email protected]/is_string.ts";
5+
46
// TODO:(miyauci) Packaging and externalization this module.
57

68
export type UppercaseLetter =

mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
// This module is browser compatible.
33

44
export { parseAcceptRanges } from "./parse.ts";
5+
export { stringifyAcceptRanges } from "./stringify.ts";
56
export type { AcceptRanges } from "./types.ts";
67
export { type Token } from "./deps.ts";

stringify.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { isString } from "./deps.ts";
2+
import { isTokenFormat } from "./utils.ts";
3+
import { Msg } from "./constants.ts";
4+
5+
/** Serialize string of array into string.
6+
*
7+
* @example
8+
* ```ts
9+
* import { stringifyAcceptRanges } from "https://deno.land/x/accept_ranges_parser@$VERSION/stringify.ts";
10+
* import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
11+
*
12+
* assertEquals(stringifyAcceptRanges(["bytes"]), "bytes");
13+
* ```
14+
*
15+
* @throws {TypeError} If the input is invalid [`<range-unit>`](https://www.rfc-editor.org/rfc/rfc9110#section-14.1-3) format.
16+
*/
17+
export function stringifyAcceptRanges(
18+
acceptRanges: string | readonly [string, ...string[]],
19+
): string {
20+
const targets = isString(acceptRanges) ? [acceptRanges] : acceptRanges;
21+
22+
targets.forEach((rangeUnit) => {
23+
if (!isTokenFormat(rangeUnit)) {
24+
throw TypeError(`${Msg.InvalidRangeUnit} "${rangeUnit}"`);
25+
}
26+
});
27+
28+
return targets.join(", ");
29+
}

stringify_test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { stringifyAcceptRanges } from "./stringify.ts";
2+
import {
3+
assertEquals,
4+
assertIsError,
5+
assertThrows,
6+
describe,
7+
it,
8+
} from "./_dev_deps.ts";
9+
10+
describe("stringifyAcceptRanges", () => {
11+
it("should return string if the input is valid string", () => {
12+
const table: string[] = ["bytes", "none"];
13+
14+
table.forEach((input) => {
15+
assertEquals(stringifyAcceptRanges(input), input);
16+
});
17+
});
18+
19+
it("should return string if the input is valid string of array", () => {
20+
const table: [[string, ...string[]], string][] = [
21+
[["bytes"], "bytes"],
22+
[["bytes", "unknown"], "bytes, unknown"],
23+
];
24+
25+
table.forEach(([input, expected]) => {
26+
assertEquals(stringifyAcceptRanges(input), expected);
27+
});
28+
});
29+
30+
it("should throw error if the input is invalid string", () => {
31+
const table: string[] = [
32+
"",
33+
" ",
34+
"bytes, none",
35+
"a ",
36+
" a",
37+
",",
38+
" ,",
39+
`"a"`,
40+
`"a, b"`,
41+
];
42+
43+
table.forEach((input) => {
44+
assertThrows(() => stringifyAcceptRanges(input));
45+
});
46+
});
47+
48+
it("should throw error if the array input has is invalid string", () => {
49+
const table: [string, ...string[]][] = [
50+
[""],
51+
["", ""],
52+
["", "", "", ""],
53+
["", "ok"],
54+
["ng", ","],
55+
];
56+
57+
table.forEach((input) => {
58+
assertThrows(() => stringifyAcceptRanges(input));
59+
});
60+
});
61+
62+
it("should be error message", () => {
63+
let err;
64+
try {
65+
stringifyAcceptRanges("");
66+
} catch (e) {
67+
err = e;
68+
} finally {
69+
assertIsError(err, TypeError, `invalid <range-unit> syntax. ""`);
70+
}
71+
});
72+
});

0 commit comments

Comments
 (0)