Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/malta.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"pages": [
["Hex encoding", "/examples/hex"],
["Base64 encoding", "/examples/base64"],
["Base32 encoding", "/examples/base32"]
["Base32 encoding", "/examples/base32"],
["ASCII encoding", "/examples/ascii"]
]
},
{
Expand Down
17 changes: 17 additions & 0 deletions docs/pages/examples/ascii.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "ASCII encoding"
---

# ASCII

Use `encodeASCII()` to ASCII encode strings to byte sequences. Use `decodeASCII()` to decode into a string.

Use `isValidASCIIEncoding()` to validate an ASCII byte sequence without decoding it.

```ts
import { encodeASCII, decodeASCII, isValidASCIIEncoding } from "@oslojs/encoding";

const encoded = encodeASCII("Hello world!");
const decoded = decodeASCII(encoded);
const valid = isValidASCIIEncoding(encoded);
```
11 changes: 11 additions & 0 deletions docs/pages/reference/main/decodeASCII.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: "decodeASCII()"
---

# decodeASCII()

ASCII decodes a byte sequence into a string. Throws a `TypeError` if the encoding is invalid.

```ts
function decodeASCII(bytes: Uint8Array): string;
```
11 changes: 11 additions & 0 deletions docs/pages/reference/main/encodeASCII.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: "encodeASCII()"
---

# encodeASCII()

ASCII encodes a string into a byte sequence. Throws a `TypeError` on invalid characters.

```ts
function encodeASCII(s: string): Uint8Array;
```
3 changes: 3 additions & 0 deletions docs/pages/reference/main/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ title: "@oslojs/encoding"

# Functions

- [`decodeASCII()`](/reference/main/decodeASCII)
- [`decodeBase32()`](/reference/main/decodeBase32)
- [`decodeBase32IgnorePadding()`](/reference/main/decodeBase32IgnorePadding)
- [`decodeBase64()`](/reference/main/decodeBase64)
- [`decodeBase64IgnorePadding()`](/reference/main/decodeBase64IgnorePadding)
- [`decodeBase64url()`](/reference/main/decodeBase64url)
- [`decodeBase64urlIgnorePadding()`](/reference/main/decodeBase64urlIgnorePadding)
- [`decodeHex()`](/reference/main/decodeHex)
- [`encodeASCII()`](/reference/main/encodeASCII)
- [`encodeBase32LowerCase()`](/reference/main/encodeBase32LowerCase)
- [`encodeBase32LowerCaseNoPadding()`](/reference/main/encodeBase32LowerCaseNoPadding)
- [`encodeBase32UpperCase()`](/reference/main/encodeBase32UpperCase)
Expand All @@ -23,5 +25,6 @@ title: "@oslojs/encoding"
- [`encodeBase64urlNoPadding()`](/reference/main/encodeBase64urlNoPadding)
- [`encodeHexLowerCase()`](/reference/main/encodeHexLowerCase)
- [`encodeHexUpperCase()`](/reference/main/encodeHexUpperCase)
- [`isValidASCIIEncoding()`](/reference/main/isValidASCIIEncoding)
- _Replaced_ [`encodeBase32()`](/reference/main/encodeBase32)
- _Replaced_ [`encodeBase32NoPadding()`](/reference/main/encodeBase32NoPadding)
11 changes: 11 additions & 0 deletions docs/pages/reference/main/isValidASCIIEncoding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: "isValidASCIIEncoding()"
---

# isValidASCIIEncoding()

Reports whether the byte sequence is a valid ASCII encoding.

```ts
function isValidASCIIEncoding(bytes: Uint8Array): boolean;
```
75 changes: 75 additions & 0 deletions src/ascii.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import * as vitest from "vitest";

import { decodeASCII, encodeASCII, isValidASCIIEncoding } from "./ascii.js";

vitest.describe("encodeASCII()", () => {
vitest.test("valid code points", () => {
for (let i = 0; i <= 0x7f; i++) {
const s = String.fromCodePoint(i);
const result = encodeASCII(s);
const expected = new TextEncoder().encode(s);
vitest.expect(result, `test code point ${i}`).toEqual(expected);
}
});

vitest.test("multiple valid code points", () => {
for (let i = 0; i <= 0x7f; i++) {
for (let j = 0; j <= 0x7f; j++) {
const s = String.fromCodePoint(i, j);
const result = encodeASCII(s);
const expected = new TextEncoder().encode(s);
vitest.expect(result, `test code points ${i}, ${j}`).toEqual(expected);
}
}
});

vitest.test(" invalid ascii", () => {
const s = String.fromCodePoint(0x8f);
vitest.expect(() => encodeASCII(s)).toThrow(TypeError);
});
});

vitest.describe("decodeASCII()", () => {
vitest.test("valid code point", () => {
for (let i = 0; i <= 0x7f; i++) {
const s = String.fromCodePoint(i);
const encoded = encodeASCII(s);
const result = decodeASCII(encoded);
vitest.expect(result, `test code point ${i}`).toBe(s);
}
});

vitest.test("multiple valid code points", () => {
for (let i = 0; i <= 0x7f; i++) {
for (let j = 0; j <= 0x7f; j++) {
const s = String.fromCodePoint(i, j);
const encoded = encodeASCII(s);
const result = decodeASCII(encoded);
vitest.expect(result, `test code points ${i}, ${j}`).toBe(s);
}
}
});

vitest.test(" invalid code point", () => {
const bytes = new Uint8Array([0x80]);
vitest.expect(() => decodeASCII(bytes)).toThrow(TypeError);
});
});

vitest.describe("isValidASCIIEncoding()", () => {
vitest.test("valid", () => {
for (let i = 0; i <= 0x7f; i++) {
for (let j = 0; j <= 0x7f; j++) {
const encoded = new Uint8Array([i, j]);
const result = isValidASCIIEncoding(encoded);
vitest.expect(result, `test code points ${i}, ${j}`).toBe(true);
}
}
});

vitest.test("invalid code point", () => {
const bytes = new Uint8Array([0x80]);
const result = isValidASCIIEncoding(bytes);
vitest.expect(result).toBe(false);
});
});
37 changes: 37 additions & 0 deletions src/ascii.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/** ASCII encodes a string into a byte sequence. Throws a `TypeError` on invalid characters. */
export function encodeASCII(s: string): Uint8Array {
const bytes = new Uint8Array(s.length);
for (let i = 0; i < s.length; i++) {
const charCode = s.charCodeAt(i);
if (Number.isNaN(charCode)) {
throw new TypeError("Invalid character");
}
if (charCode > 0x7f) {
throw new TypeError("Invalid character");
}
bytes[i] = charCode;
}
return bytes;
}

/** ASCII decodes a byte sequence into a string. Throws a `TypeError` if the encoding is invalid. */
export function decodeASCII(bytes: Uint8Array): string {
let s = "";
for (let i = 0; i < bytes.length; i++) {
if (bytes[i] > 0x7f) {
throw new TypeError("Invalid encoding");
}
s += String.fromCharCode(bytes[i]);
}
return s;
}

/** Reports whether the byte sequence is a valid ASCII encoding. */
export function isValidASCIIEncoding(bytes: Uint8Array): boolean {
for (let i = 0; i < bytes.length; i++) {
if (bytes[i] > 0x7f) {
return false;
}
}
return true;
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export {
decodeBase64url,
decodeBase64urlIgnorePadding
} from "./base64.js";
export { encodeASCII, decodeASCII, isValidASCIIEncoding } from "./ascii.js";