Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING(encoding): remove deprecated VarInt APIs #4864

Merged
merged 2 commits into from
May 30, 2024
Merged
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
10 changes: 1 addition & 9 deletions encoding/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,4 @@ export * from "./base58.ts";
export * from "./base64.ts";
export * from "./base64url.ts";
export * from "./hex.ts";
// TODO: change to * after varint decode/encode functions are removed
export {
decodeVarint,
decodeVarint32,
encodeVarint,
MaxUInt64,
MaxVarIntLen32,
MaxVarIntLen64,
} from "./varint.ts";
export * from "./varint.ts";
102 changes: 0 additions & 102 deletions encoding/varint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,39 +54,6 @@ const AB = new ArrayBuffer(8);
const U32_VIEW = new Uint32Array(AB);
const U64_VIEW = new BigUint64Array(AB);

/**
* Given a non empty `buf`, starting at `offset` (default: 0), begin decoding bytes as
* VarInt encoded bytes, for a maximum of 10 bytes (offset + 10). The returned
* tuple is of the decoded varint 32-bit number, and the new offset with which
* to continue decoding other data.
*
* If a `bigint` in return is undesired, the `decode32` function will return a
* `number`, but this should only be used in cases where the varint is
* _assured_ to be 32-bits. If in doubt, use `decode()`.
*
* To know how many bytes the VarInt took to encode, simply negate `offset`
* from the returned new `offset`.
*
* @param buf The buffer to decode from.
* @param offset The offset to start decoding from.
* @returns A tuple of the decoded varint 64-bit number, and the new offset.
*
* @example
* ```ts
* import { decode } from "@std/encoding/varint";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const buf = new Uint8Array([0x8E, 0x02]);
* assertEquals(decode(buf), [ 300n, 2 ]);
* ```
*
* @deprecated This will be removed in 1.0.0. Use {@linkcode decodeVarint}
* instead.
*/
export function decode(buf: Uint8Array, offset = 0): [bigint, number] {
return decodeVarint(buf, offset);
}

/**
* Given a non empty `buf`, starting at `offset` (default: 0), begin decoding bytes as
* VarInt encoded bytes, for a maximum of 10 bytes (offset + 10). The returned
Expand Down Expand Up @@ -174,38 +141,6 @@ export function decodeVarint(buf: Uint8Array, offset = 0): [bigint, number] {
return [U64_VIEW[0], i];
}

/**
* Given a `buf`, starting at `offset` (default: 0), begin decoding bytes as
* VarInt encoded bytes, for a maximum of 5 bytes (offset + 5). The returned
* tuple is of the decoded varint 32-bit number, and the new offset with which
* to continue decoding other data.
*
* VarInts are _not 32-bit by default_ so this should only be used in cases
* where the varint is _assured_ to be 32-bits. If in doubt, use `decode()`.
*
* To know how many bytes the VarInt took to encode, simply negate `offset`
* from the returned new `offset`.
*
* @param buf The buffer to decode from.
* @param offset The offset to start decoding from.
* @returns A tuple of the decoded varint 32-bit number, and the new offset.
*
* @example
* ```ts
* import { decode32 } from "@std/encoding/varint";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const buf = new Uint8Array([0x8E, 0x02]);
* assertEquals(decode32(buf), [ 300, 2 ]);
* ```
*
* @deprecated This will be removed in 1.0.0. Use {@linkcode decodeVarint32}
* instead.
*/
export function decode32(buf: Uint8Array, offset = 0): [number, number] {
return decodeVarint32(buf, offset);
}

/**
* Given a `buf`, starting at `offset` (default: 0), begin decoding bytes as
* VarInt encoded bytes, for a maximum of 5 bytes (offset + 5). The returned
Expand Down Expand Up @@ -246,43 +181,6 @@ export function decodeVarint32(buf: Uint8Array, offset = 0): [number, number] {
throw new RangeError("malformed or overflow varint");
}

/**
* Takes unsigned number `num` and converts it into a VarInt encoded
* `Uint8Array`, returning a tuple consisting of a `Uint8Array` slice of the
* encoded VarInt, and an offset where the VarInt encoded bytes end within the
* `Uint8Array`.
*
* If `buf` is not given then a Uint8Array will be created.
* `offset` defaults to `0`.
*
* If passed `buf` then that will be written into, starting at `offset`. The
* resulting returned `Uint8Array` will be a slice of `buf`. The resulting
* returned number is effectively `offset + bytesWritten`.
*
* @param num The number to encode.
* @param buf The buffer to write into.
* @param offset The offset to start writing at.
* @returns A tuple of the encoded VarInt `Uint8Array` and the new offset.
*
* @example
* ```ts
* import { encode } from "@std/encoding/varint";
* import { assertEquals } from "@std/assert/assert-equals";
*
* const buf = new Uint8Array(10);
* assertEquals(encode(42n, buf), [new Uint8Array([42]), 1]);
* ```
*
* @deprecated This will be removed in 1.0.0. Use {@linkcode encodeVarint} instead.
*/
export function encode(
num: bigint | number,
buf: Uint8Array = new Uint8Array(MaxVarIntLen64),
offset = 0,
): [Uint8Array, number] {
return encodeVarint(num, buf, offset);
}

/**
* Takes unsigned number `num` and converts it into a VarInt encoded
* `Uint8Array`, returning a tuple consisting of a `Uint8Array` slice of the
Expand Down
89 changes: 52 additions & 37 deletions encoding/varint_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,50 @@

import { assertEquals, assertThrows } from "@std/assert";
import {
decode,
decode32,
encode,
decodeVarint,
decodeVarint32,
encodeVarint,
MaxUInt64,
MaxVarIntLen64,
} from "./varint.ts";

function encodeDecode(i: number | bigint) {
const [buf, n] = encode(i, new Uint8Array(MaxVarIntLen64));
const fn = (typeof i === "bigint") ? decode : decode32;
const [buf, n] = encodeVarint(i, new Uint8Array(MaxVarIntLen64));
const fn = (typeof i === "bigint") ? decodeVarint : decodeVarint32;
const [j, m] = fn(buf);
assertEquals(i, j, `${fn.name}(encode(${i})): ${i} !== ${j}`);
assertEquals(n, m, `${fn.name}(encode(${i})): buffer lengths ${n} !== ${m}`);
assertEquals(i, j, `${fn.name}(encodeVarint(${i})): ${i} !== ${j}`);
assertEquals(
n,
m,
`${fn.name}(encodeVarint(${i})): buffer lengths ${n} !== ${m}`,
);
}

Deno.test("decode() handles empty buff", () => {
assertThrows(() => decode(Uint8Array.of()), RangeError);
Deno.test("decodeVarint() handles empty buff", () => {
assertThrows(() => decodeVarint(Uint8Array.of()), RangeError);
});

Deno.test("decode() handles manual", () => {
assertEquals(decode(Uint8Array.of(172, 2)), [300n, 2]);
Deno.test("decodeVarint() handles manual", () => {
assertEquals(decodeVarint(Uint8Array.of(172, 2)), [300n, 2]);
});
Deno.test("decode() handles max size", () => {
Deno.test("decodeVarint() handles max size", () => {
assertEquals(
decode(Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 255, 1)),
decodeVarint(Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 255, 1)),
[18446744073709551615n, 10],
);
});
Deno.test("decode() throws on overflow", () => {
Deno.test("decodeVarint() throws on overflow", () => {
assertThrows(
() => decode(Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 255, 2)),
() =>
decodeVarint(
Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 255, 2),
),
RangeError,
);
});
Deno.test("decode() handles with offset", () => {
Deno.test("decodeVarint() handles with offset", () => {
assertEquals(
decode(
decodeVarint(
Uint8Array.of(
255,
255,
Expand All @@ -62,56 +69,64 @@ Deno.test("decode() handles with offset", () => {
[18446744073709551615n, 14],
);
});
Deno.test("decode32() handles manual", () => {
assertEquals(decode32(Uint8Array.of(172, 2)), [300, 2]);
Deno.test("decodeVarint32() handles manual", () => {
assertEquals(decodeVarint32(Uint8Array.of(172, 2)), [300, 2]);
});
Deno.test("decode32() handles max size", () => {
Deno.test("decodeVarint32() handles max size", () => {
assertEquals(
decode32(Uint8Array.of(255, 255, 255, 255, 15, 0, 0, 0, 0, 0)),
decodeVarint32(Uint8Array.of(255, 255, 255, 255, 15, 0, 0, 0, 0, 0)),
[4294967295, 5],
);
});
Deno.test("decode32() throws on overflow", () => {
Deno.test("decodeVarint32() throws on overflow", () => {
assertThrows(
() =>
decode32(Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 15, 0)),
decodeVarint32(
Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 15, 0),
),
RangeError,
);
});
Deno.test("decode32() handles with offset", () => {
Deno.test("decodeVarint32() handles with offset", () => {
assertEquals(
decode32(Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 15, 0), 4),
decodeVarint32(
Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 15, 0),
4,
),
[4294967295, 9],
);
});
Deno.test("encode() handles manual", () => {
assertEquals(encode(300, new Uint8Array(2)), [Uint8Array.of(172, 2), 2]);
Deno.test("encodeVarint() handles manual", () => {
assertEquals(encodeVarint(300, new Uint8Array(2)), [
Uint8Array.of(172, 2),
2,
]);
assertEquals(
encode(4294967295),
encodeVarint(4294967295),
[Uint8Array.of(255, 255, 255, 255, 15), 5],
);
assertEquals(
encode(18446744073709551615n),
encodeVarint(18446744073709551615n),
[Uint8Array.of(255, 255, 255, 255, 255, 255, 255, 255, 255, 1), 10],
);
});
Deno.test("encode() throws on overflow uint64", () => {
assertThrows(() => encode(1e+30), RangeError, "overflows uint64");
Deno.test("encodeVarint() throws on overflow uint64", () => {
assertThrows(() => encodeVarint(1e+30), RangeError, "overflows uint64");
});
Deno.test("encode() throws on overflow with negative", () => {
assertThrows(() => encode(-1), RangeError, "signed input given");
Deno.test("encodeVarint() throws on overflow with negative", () => {
assertThrows(() => encodeVarint(-1), RangeError, "signed input given");
});
Deno.test("encode() encodes with offset", () => {
Deno.test("encodeVarint() encodes with offset", () => {
let uint = new Uint8Array(3);
assertEquals(
encode(300, uint, 1),
encodeVarint(300, uint, 1),
[Uint8Array.of(172, 2), 3],
);
assertEquals(uint, Uint8Array.of(0, 172, 2));
uint = new Uint8Array(MaxVarIntLen64);
uint[0] = uint[1] = uint[2] = 12;
assertEquals(
encode(4294967295, uint, 3),
encodeVarint(4294967295, uint, 3),
[Uint8Array.of(255, 255, 255, 255, 15), 8],
);
assertEquals(uint, Uint8Array.of(12, 12, 12, 255, 255, 255, 255, 15, 0, 0));
Expand Down Expand Up @@ -143,7 +158,7 @@ Deno.test("encodeDecode() handles BigInt", () => {
encodeDecode(i);
}
});
Deno.test("encodeDecode() handles decode32", () => {
Deno.test("encodeDecode() handles decodeVarint32", () => {
for (
const i of [
0,
Expand Down