diff --git a/README.md b/README.md index 113d10f..418919a 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,10 @@ Throws a `TypeError` if the object contains an invalid type or parameter names. This package exposes the validation functions used by `format`: -- `isTypeValid` Validates the MIME type against RFC 9110. -- `isTokenValid` Validates a token against RFC 9110 (used for the parameter name). +- `isTypeValid(str, start?, end?)` Validates the MIME type against RFC 9110. +- `isTokenValid(str, start?, end?)` Validates a token against RFC 9110 (used for the parameter name). + +Passing `start` and `end` allows for validating a subset of a string, instead of using `str#slice`. ## License diff --git a/src/index.ts b/src/index.ts index a8f2cc0..a89b04e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -68,15 +68,18 @@ export interface ContentType { /** * Validate a type string against RFC 9110. */ -export function isTypeValid(type: string): boolean { - const len = type.length; +export function isTypeValid( + type: string, + start = 0, + end = type.length, +): boolean { let hasSlash = false; - for (let index = 0; index < len; index++) { + for (let index = start; index < end; index++) { const code = type.charCodeAt(index); if (code === 47 /* / */) { - if (hasSlash || index === 0 || index === len - 1) return false; + if (hasSlash || index === start || index >= end - 1) return false; hasSlash = true; } else if (!isTokenCode(code)) { return false; @@ -89,12 +92,15 @@ export function isTypeValid(type: string): boolean { /** * Validate a token against RFC 9110. */ -export function isTokenValid(name: string): boolean { - const len = name.length; - if (len === 0) return false; +export function isTokenValid( + token: string, + start = 0, + end = token.length, +): boolean { + if (start >= end) return false; - for (let index = 0; index < len; index++) { - if (!isTokenCode(name.charCodeAt(index))) return false; + for (let index = start; index < end; index++) { + if (!isTokenCode(token.charCodeAt(index))) return false; } return true; diff --git a/src/validation.spec.ts b/src/validation.spec.ts index 3f36e29..888cd9c 100644 --- a/src/validation.spec.ts +++ b/src/validation.spec.ts @@ -28,6 +28,30 @@ describe("isTypeValid(type)", function () { ])("should reject invalid type: %s", function (type) { assert.strictEqual(isTypeValid(type), false); }); + + it("should default the end index to the string length", function () { + assert.strictEqual(isTypeValid(";text/html", 1), true); + }); + + it.each([ + ["text/html;", 0, 9, true], + [";text/html;", 1, 10, true], + [";a/b;", 1, 4, true], + [";text/html;", 0, 10, false], + [";text/html;", 1, 11, false], + [";text/html;", 5, 10, false], + [";text/html;", 1, 6, false], + [";text/html;", 1, 5, false], + [";text/html/extra;", 1, 16, false], + [";text/ plain;", 1, 12, false], + [";text/html;", 1, 1, false], + [";text/html;", 10, 1, false], + ])( + "should validate type %j from %i to %i as %s", + function (type, start, end, expected) { + assert.strictEqual(isTypeValid(type, start, end), expected); + }, + ); }); describe("isTokenValid(name)", function () { @@ -62,4 +86,26 @@ describe("isTokenValid(name)", function () { ])("should reject invalid parameter name: %s", function (name) { assert.strictEqual(isTokenValid(name), false); }); + + it("should default the end index to the string length", function () { + assert.strictEqual(isTokenValid(";charset", 1), true); + }); + + it.each([ + ["charset=", 0, 7, true], + [";charset=", 1, 8, true], + [";a=", 1, 2, true], + [";charset=", 0, 8, false], + [";charset=", 1, 9, false], + [";char set=", 1, 9, false], + [";char/set=", 1, 9, false], + [";chärset=", 1, 8, false], + [";charset=", 1, 1, false], + [";charset=", 8, 1, false], + ])( + "should validate parameter name %j from %i to %i as %s", + function (name, start, end, expected) { + assert.strictEqual(isTokenValid(name, start, end), expected); + }, + ); });