summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--std/util/sha1.ts (renamed from std/ws/sha1.ts)5
-rw-r--r--std/util/sha1_test.ts (renamed from std/ws/sha1_test.ts)6
-rw-r--r--std/uuid/_common.ts31
-rw-r--r--std/uuid/mod.ts6
-rwxr-xr-xstd/uuid/test.ts4
-rw-r--r--std/uuid/tests/v5/generate.ts66
-rw-r--r--std/uuid/tests/v5/validate.ts19
-rw-r--r--std/uuid/v5.ts52
-rw-r--r--std/ws/mod.ts2
9 files changed, 180 insertions, 11 deletions
diff --git a/std/ws/sha1.ts b/std/util/sha1.ts
index fc86881f8..bb9103d27 100644
--- a/std/ws/sha1.ts
+++ b/std/util/sha1.ts
@@ -47,9 +47,9 @@ export class Sha1 {
this._finalized = this._hashed = false;
}
- update(data: string | ArrayBuffer | ArrayBufferView): void {
+ update(data: string | ArrayBuffer | ArrayBufferView): Sha1 {
if (this._finalized) {
- return;
+ return this;
}
let notString = true;
let message;
@@ -119,6 +119,7 @@ export class Sha1 {
this._hBytes += (this._bytes / 4294967296) >>> 0;
this._bytes = this._bytes >>> 0;
}
+ return this;
}
finalize(): void {
diff --git a/std/ws/sha1_test.ts b/std/util/sha1_test.ts
index 8830173a4..159bdd94d 100644
--- a/std/ws/sha1_test.ts
+++ b/std/util/sha1_test.ts
@@ -3,20 +3,20 @@ const { test } = Deno;
import { assertEquals } from "../testing/asserts.ts";
import { Sha1 } from "./sha1.ts";
-test("[ws/sha] test1", () => {
+test("[util/sha] test1", () => {
const sha1 = new Sha1();
sha1.update("abcde");
assertEquals(sha1.toString(), "03de6c570bfe24bfc328ccd7ca46b76eadaf4334");
});
-test("[ws/sha] testWithArray", () => {
+test("[util/sha] testWithArray", () => {
const data = Uint8Array.of(0x61, 0x62, 0x63, 0x64, 0x65);
const sha1 = new Sha1();
sha1.update(data);
assertEquals(sha1.toString(), "03de6c570bfe24bfc328ccd7ca46b76eadaf4334");
});
-test("[ws/sha] testSha1WithBuffer", () => {
+test("[util/sha] testSha1WithBuffer", () => {
const data = Uint8Array.of(0x61, 0x62, 0x63, 0x64, 0x65);
const sha1 = new Sha1();
sha1.update(data.buffer);
diff --git a/std/uuid/_common.ts b/std/uuid/_common.ts
index b0cad2584..8f13ac7e3 100644
--- a/std/uuid/_common.ts
+++ b/std/uuid/_common.ts
@@ -13,6 +13,35 @@ export function bytesToUuid(bytes: number[] | Uint8Array): string {
"-",
...bits.slice(8, 10),
"-",
- ...bits.slice(10),
+ ...bits.slice(10, 16),
].join("");
}
+
+export function uuidToBytes(uuid: string): number[] {
+ const bytes: number[] = [];
+
+ uuid.replace(/[a-fA-F0-9]{2}/g, (hex: string): string => {
+ bytes.push(parseInt(hex, 16));
+ return "";
+ });
+
+ return bytes;
+}
+
+export function stringToBytes(str: string): number[] {
+ str = unescape(encodeURIComponent(str));
+ const bytes = new Array(str.length);
+ for (let i = 0; i < str.length; i++) {
+ bytes[i] = str.charCodeAt(i);
+ }
+ return bytes;
+}
+
+export function createBuffer(content: number[]): ArrayBuffer {
+ const arrayBuffer = new ArrayBuffer(content.length);
+ const uint8Array = new Uint8Array(arrayBuffer);
+ for (let i = 0; i < content.length; i++) {
+ uint8Array[i] = content[i];
+ }
+ return arrayBuffer;
+}
diff --git a/std/uuid/mod.ts b/std/uuid/mod.ts
index 23d0c6410..7ffbb1349 100644
--- a/std/uuid/mod.ts
+++ b/std/uuid/mod.ts
@@ -2,6 +2,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import * as v1 from "./v1.ts";
import * as v4 from "./v4.ts";
+import * as v5 from "./v5.ts";
export const NIL_UUID = "00000000-0000-0000-0000-000000000000";
@@ -21,7 +22,4 @@ const NOT_IMPLEMENTED = {
// TODO Implement
export const v3 = NOT_IMPLEMENTED;
-export { v1, v4 };
-
-// TODO Implement
-export const v5 = NOT_IMPLEMENTED;
+export { v1, v4, v5 };
diff --git a/std/uuid/test.ts b/std/uuid/test.ts
index 74d3c093d..58eae2fff 100755
--- a/std/uuid/test.ts
+++ b/std/uuid/test.ts
@@ -11,3 +11,7 @@ import "./tests/v1/generate.ts";
// V4 Tests
import "./tests/v4/validate.ts";
import "./tests/v4/generate.ts";
+
+// V5 Tests
+import "./tests/v5/validate.ts";
+import "./tests/v5/generate.ts";
diff --git a/std/uuid/tests/v5/generate.ts b/std/uuid/tests/v5/generate.ts
new file mode 100644
index 000000000..c869ef505
--- /dev/null
+++ b/std/uuid/tests/v5/generate.ts
@@ -0,0 +1,66 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { assert, assertEquals } from "../../../testing/asserts.ts";
+const { test } = Deno;
+import { generate, validate } from "../../v5.ts";
+const NAMESPACE = "1b671a64-40d5-491e-99b0-da01ff1f3341";
+test({
+ name: "[UUID] test_uuid_v5",
+ fn(): void {
+ const u = generate({ value: "", namespace: NAMESPACE });
+ assertEquals(typeof u, "string", "returns a string");
+ assert(u !== "", "return string is not empty");
+ },
+});
+
+test({
+ name: "[UUID] test_uuid_v5_format",
+ fn(): void {
+ for (let i = 0; i < 10000; i++) {
+ const u = generate({ value: String(i), namespace: NAMESPACE }) as string;
+ assert(validate(u), `${u} is not a valid uuid v5`);
+ }
+ },
+});
+
+test({
+ name: "[UUID] test_uuid_v5_option",
+ fn(): void {
+ const v5Options = {
+ value: "Hello, World",
+ namespace: NAMESPACE,
+ };
+ const u = generate(v5Options);
+ assertEquals(u, "4b4f2adc-5b27-57b5-8e3a-c4c4bcf94f05");
+ },
+});
+
+test({
+ name: "[UUID] test_uuid_v5_buf_offset",
+ fn(): void {
+ const buf = [
+ 75,
+ 79,
+ 42,
+ 220,
+ 91,
+ 39,
+ 87,
+ 181,
+ 142,
+ 58,
+ 196,
+ 196,
+ 188,
+ 249,
+ 79,
+ 5,
+ ];
+ const origin = JSON.parse(JSON.stringify(buf));
+ generate({ value: "Hello, World", namespace: NAMESPACE }, buf);
+ assertEquals(origin, buf);
+
+ generate({ value: "Hello, World", namespace: NAMESPACE }, buf, 3);
+ assertEquals(origin.slice(0, 3), buf.slice(0, 3));
+ assertEquals(origin, buf.slice(3));
+ },
+});
diff --git a/std/uuid/tests/v5/validate.ts b/std/uuid/tests/v5/validate.ts
new file mode 100644
index 000000000..888acb1c5
--- /dev/null
+++ b/std/uuid/tests/v5/validate.ts
@@ -0,0 +1,19 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { assert } from "../../../testing/asserts.ts";
+import { generate, validate } from "../../v5.ts";
+
+Deno.test({
+ name: "[UUID] is_valid_uuid_v5",
+ fn(): void {
+ const u = generate({
+ value: "Hello, World",
+ namespace: "1b671a64-40d5-491e-99b0-da01ff1f3341",
+ }) as string;
+ const t = "4b4f2adc-5b27-57b5-8e3a-c4c4bcf94f05";
+ const n = "4b4f2adc-5b27-17b5-8e3a-c4c4bcf94f05";
+
+ assert(validate(u), `generated ${u} should be valid`);
+ assert(validate(t), `${t} should be valid`);
+ assert(!validate(n), `${n} should not be valid`);
+ },
+});
diff --git a/std/uuid/v5.ts b/std/uuid/v5.ts
new file mode 100644
index 000000000..1216762dd
--- /dev/null
+++ b/std/uuid/v5.ts
@@ -0,0 +1,52 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+import {
+ bytesToUuid,
+ createBuffer,
+ stringToBytes,
+ uuidToBytes,
+} from "./_common.ts";
+import { Sha1 } from "../util/sha1.ts";
+import { isString } from "../node/util.ts";
+import { assert } from "../testing/asserts.ts";
+
+const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+
+export function validate(id: string): boolean {
+ return UUID_RE.test(id);
+}
+
+interface V5Options {
+ value: string | number[];
+ namespace: string | number[];
+}
+
+export function generate(
+ options: V5Options,
+ buf?: number[],
+ offset?: number
+): string | number[] {
+ const i = (buf && offset) || 0;
+
+ let { value, namespace } = options;
+ if (isString(value)) value = stringToBytes(value as string);
+ if (isString(namespace)) namespace = uuidToBytes(namespace as string);
+ assert(
+ namespace.length === 16,
+ "namespace must be uuid string or an Array of 16 byte values"
+ );
+
+ const content = (namespace as number[]).concat(value as number[]);
+ const bytes = new Sha1().update(createBuffer(content)).digest();
+
+ bytes[6] = (bytes[6] & 0x0f) | 0x50;
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
+
+ if (buf) {
+ for (let idx = 0; idx < 16; ++idx) {
+ buf[i + idx] = bytes[idx];
+ }
+ }
+
+ return buf || bytesToUuid(bytes);
+}
diff --git a/std/ws/mod.ts b/std/ws/mod.ts
index 87084312f..9632fbbfb 100644
--- a/std/ws/mod.ts
+++ b/std/ws/mod.ts
@@ -4,7 +4,7 @@ import { decode, encode } from "../encoding/utf8.ts";
import { hasOwnProperty } from "../util/has_own_property.ts";
import { BufReader, BufWriter } from "../io/bufio.ts";
import { readLong, readShort, sliceLongToBytes } from "../io/ioutil.ts";
-import { Sha1 } from "./sha1.ts";
+import { Sha1 } from "../util/sha1.ts";
import { writeResponse } from "../http/io.ts";
import { TextProtoReader } from "../textproto/mod.ts";
import { Deferred, deferred } from "../util/async.ts";