summaryrefslogtreecommitdiff
path: root/std/encoding/yaml/type
diff options
context:
space:
mode:
Diffstat (limited to 'std/encoding/yaml/type')
-rw-r--r--std/encoding/yaml/type/binary.ts139
-rw-r--r--std/encoding/yaml/type/bool.ts39
-rw-r--r--std/encoding/yaml/type/float.ts125
-rw-r--r--std/encoding/yaml/type/int.ts191
-rw-r--r--std/encoding/yaml/type/map.ts14
-rw-r--r--std/encoding/yaml/type/merge.ts15
-rw-r--r--std/encoding/yaml/type/mod.ts18
-rw-r--r--std/encoding/yaml/type/nil.ts45
-rw-r--r--std/encoding/yaml/type/omap.ts46
-rw-r--r--std/encoding/yaml/type/pairs.ts49
-rw-r--r--std/encoding/yaml/type/seq.ts14
-rw-r--r--std/encoding/yaml/type/set.ts31
-rw-r--r--std/encoding/yaml/type/str.ts12
-rw-r--r--std/encoding/yaml/type/timestamp.ts96
14 files changed, 834 insertions, 0 deletions
diff --git a/std/encoding/yaml/type/binary.ts b/std/encoding/yaml/type/binary.ts
new file mode 100644
index 000000000..7c4fc1f06
--- /dev/null
+++ b/std/encoding/yaml/type/binary.ts
@@ -0,0 +1,139 @@
+// Ported from js-yaml v3.13.1:
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+const { Buffer } = Deno;
+
+// [ 64, 65, 66 ] -> [ padding, CR, LF ]
+const BASE64_MAP =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";
+
+function resolveYamlBinary(data: Any): boolean {
+ if (data === null) return false;
+
+ let code: number;
+ let bitlen = 0;
+ const max = data.length;
+ const map = BASE64_MAP;
+
+ // Convert one by one.
+ for (let idx = 0; idx < max; idx++) {
+ code = map.indexOf(data.charAt(idx));
+
+ // Skip CR/LF
+ if (code > 64) continue;
+
+ // Fail on illegal characters
+ if (code < 0) return false;
+
+ bitlen += 6;
+ }
+
+ // If there are any bits left, source was corrupted
+ return bitlen % 8 === 0;
+}
+
+function constructYamlBinary(data: string): Deno.Buffer {
+ // remove CR/LF & padding to simplify scan
+ const input = data.replace(/[\r\n=]/g, "");
+ const max = input.length;
+ const map = BASE64_MAP;
+
+ // Collect by 6*4 bits (3 bytes)
+
+ const result = [];
+ let bits = 0;
+ for (let idx = 0; idx < max; idx++) {
+ if (idx % 4 === 0 && idx) {
+ result.push((bits >> 16) & 0xff);
+ result.push((bits >> 8) & 0xff);
+ result.push(bits & 0xff);
+ }
+
+ bits = (bits << 6) | map.indexOf(input.charAt(idx));
+ }
+
+ // Dump tail
+
+ const tailbits = (max % 4) * 6;
+
+ if (tailbits === 0) {
+ result.push((bits >> 16) & 0xff);
+ result.push((bits >> 8) & 0xff);
+ result.push(bits & 0xff);
+ } else if (tailbits === 18) {
+ result.push((bits >> 10) & 0xff);
+ result.push((bits >> 2) & 0xff);
+ } else if (tailbits === 12) {
+ result.push((bits >> 4) & 0xff);
+ }
+
+ return new Buffer(new Uint8Array(result));
+}
+
+function representYamlBinary(object: Uint8Array): string {
+ const max = object.length;
+ const map = BASE64_MAP;
+
+ // Convert every three bytes to 4 ASCII characters.
+
+ let result = "";
+ let bits = 0;
+ for (let idx = 0; idx < max; idx++) {
+ if (idx % 3 === 0 && idx) {
+ result += map[(bits >> 18) & 0x3f];
+ result += map[(bits >> 12) & 0x3f];
+ result += map[(bits >> 6) & 0x3f];
+ result += map[bits & 0x3f];
+ }
+
+ bits = (bits << 8) + object[idx];
+ }
+
+ // Dump tail
+
+ const tail = max % 3;
+
+ if (tail === 0) {
+ result += map[(bits >> 18) & 0x3f];
+ result += map[(bits >> 12) & 0x3f];
+ result += map[(bits >> 6) & 0x3f];
+ result += map[bits & 0x3f];
+ } else if (tail === 2) {
+ result += map[(bits >> 10) & 0x3f];
+ result += map[(bits >> 4) & 0x3f];
+ result += map[(bits << 2) & 0x3f];
+ result += map[64];
+ } else if (tail === 1) {
+ result += map[(bits >> 2) & 0x3f];
+ result += map[(bits << 4) & 0x3f];
+ result += map[64];
+ result += map[64];
+ }
+
+ return result;
+}
+
+function isBinary(obj: Any): obj is Deno.Buffer {
+ const buf = new Buffer();
+ try {
+ if (0 > buf.readFromSync(obj as Deno.Buffer)) return true;
+ return false;
+ } catch {
+ return false;
+ } finally {
+ buf.reset();
+ }
+}
+
+export const binary = new Type("tag:yaml.org,2002:binary", {
+ construct: constructYamlBinary,
+ kind: "scalar",
+ predicate: isBinary,
+ represent: representYamlBinary,
+ resolve: resolveYamlBinary
+});
diff --git a/std/encoding/yaml/type/bool.ts b/std/encoding/yaml/type/bool.ts
new file mode 100644
index 000000000..28e9b2e9e
--- /dev/null
+++ b/std/encoding/yaml/type/bool.ts
@@ -0,0 +1,39 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { isBoolean } from "../utils.ts";
+
+function resolveYamlBoolean(data: string): boolean {
+ const max = data.length;
+
+ return (
+ (max === 4 && (data === "true" || data === "True" || data === "TRUE")) ||
+ (max === 5 && (data === "false" || data === "False" || data === "FALSE"))
+ );
+}
+
+function constructYamlBoolean(data: string): boolean {
+ return data === "true" || data === "True" || data === "TRUE";
+}
+
+export const bool = new Type("tag:yaml.org,2002:bool", {
+ construct: constructYamlBoolean,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isBoolean,
+ represent: {
+ lowercase(object: boolean): string {
+ return object ? "true" : "false";
+ },
+ uppercase(object: boolean): string {
+ return object ? "TRUE" : "FALSE";
+ },
+ camelcase(object: boolean): string {
+ return object ? "True" : "False";
+ }
+ },
+ resolve: resolveYamlBoolean
+});
diff --git a/std/encoding/yaml/type/float.ts b/std/encoding/yaml/type/float.ts
new file mode 100644
index 000000000..359a7cc37
--- /dev/null
+++ b/std/encoding/yaml/type/float.ts
@@ -0,0 +1,125 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { StyleVariant, Type } from "../type.ts";
+import { isNegativeZero, Any } from "../utils.ts";
+
+const YAML_FLOAT_PATTERN = new RegExp(
+ // 2.5e4, 2.5 and integers
+ "^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?" +
+ // .2e4, .2
+ // special case, seems not from spec
+ "|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?" +
+ // 20:59
+ "|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*" +
+ // .inf
+ "|[-+]?\\.(?:inf|Inf|INF)" +
+ // .nan
+ "|\\.(?:nan|NaN|NAN))$"
+);
+
+function resolveYamlFloat(data: string): boolean {
+ if (
+ !YAML_FLOAT_PATTERN.test(data) ||
+ // Quick hack to not allow integers end with `_`
+ // Probably should update regexp & check speed
+ data[data.length - 1] === "_"
+ ) {
+ return false;
+ }
+
+ return true;
+}
+
+function constructYamlFloat(data: string): number {
+ let value = data.replace(/_/g, "").toLowerCase();
+ const sign = value[0] === "-" ? -1 : 1;
+ const digits: number[] = [];
+
+ if ("+-".indexOf(value[0]) >= 0) {
+ value = value.slice(1);
+ }
+
+ if (value === ".inf") {
+ return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
+ }
+ if (value === ".nan") {
+ return NaN;
+ }
+ if (value.indexOf(":") >= 0) {
+ value.split(":").forEach((v): void => {
+ digits.unshift(parseFloat(v));
+ });
+
+ let valueNb = 0.0;
+ let base = 1;
+
+ digits.forEach((d): void => {
+ valueNb += d * base;
+ base *= 60;
+ });
+
+ return sign * valueNb;
+ }
+ return sign * parseFloat(value);
+}
+
+const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
+
+function representYamlFloat(object: Any, style?: StyleVariant): Any {
+ if (isNaN(object)) {
+ switch (style) {
+ case "lowercase":
+ return ".nan";
+ case "uppercase":
+ return ".NAN";
+ case "camelcase":
+ return ".NaN";
+ }
+ } else if (Number.POSITIVE_INFINITY === object) {
+ switch (style) {
+ case "lowercase":
+ return ".inf";
+ case "uppercase":
+ return ".INF";
+ case "camelcase":
+ return ".Inf";
+ }
+ } else if (Number.NEGATIVE_INFINITY === object) {
+ switch (style) {
+ case "lowercase":
+ return "-.inf";
+ case "uppercase":
+ return "-.INF";
+ case "camelcase":
+ return "-.Inf";
+ }
+ } else if (isNegativeZero(object)) {
+ return "-0.0";
+ }
+
+ const res = object.toString(10);
+
+ // JS stringifier can build scientific format without dots: 5e-100,
+ // while YAML requres dot: 5.e-100. Fix it with simple hack
+
+ return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res;
+}
+
+function isFloat(object: Any): boolean {
+ return (
+ Object.prototype.toString.call(object) === "[object Number]" &&
+ (object % 1 !== 0 || isNegativeZero(object))
+ );
+}
+
+export const float = new Type("tag:yaml.org,2002:float", {
+ construct: constructYamlFloat,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isFloat,
+ represent: representYamlFloat,
+ resolve: resolveYamlFloat
+});
diff --git a/std/encoding/yaml/type/int.ts b/std/encoding/yaml/type/int.ts
new file mode 100644
index 000000000..d2ffb1701
--- /dev/null
+++ b/std/encoding/yaml/type/int.ts
@@ -0,0 +1,191 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { isNegativeZero, Any } from "../utils.ts";
+
+function isHexCode(c: number): boolean {
+ return (
+ (0x30 /* 0 */ <= c && c <= 0x39) /* 9 */ ||
+ (0x41 /* A */ <= c && c <= 0x46) /* F */ ||
+ (0x61 /* a */ <= c && c <= 0x66) /* f */
+ );
+}
+
+function isOctCode(c: number): boolean {
+ return 0x30 /* 0 */ <= c && c <= 0x37 /* 7 */;
+}
+
+function isDecCode(c: number): boolean {
+ return 0x30 /* 0 */ <= c && c <= 0x39 /* 9 */;
+}
+
+function resolveYamlInteger(data: string): boolean {
+ const max = data.length;
+ let index = 0;
+ let hasDigits = false;
+
+ if (!max) return false;
+
+ let ch = data[index];
+
+ // sign
+ if (ch === "-" || ch === "+") {
+ ch = data[++index];
+ }
+
+ if (ch === "0") {
+ // 0
+ if (index + 1 === max) return true;
+ ch = data[++index];
+
+ // base 2, base 8, base 16
+
+ if (ch === "b") {
+ // base 2
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === "_") continue;
+ if (ch !== "0" && ch !== "1") return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+
+ if (ch === "x") {
+ // base 16
+ index++;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === "_") continue;
+ if (!isHexCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+
+ // base 8
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === "_") continue;
+ if (!isOctCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+
+ // base 10 (except 0) or base 60
+
+ // value should not start with `_`;
+ if (ch === "_") return false;
+
+ for (; index < max; index++) {
+ ch = data[index];
+ if (ch === "_") continue;
+ if (ch === ":") break;
+ if (!isDecCode(data.charCodeAt(index))) {
+ return false;
+ }
+ hasDigits = true;
+ }
+
+ // Should have digits and should not end with `_`
+ if (!hasDigits || ch === "_") return false;
+
+ // if !base60 - done;
+ if (ch !== ":") return true;
+
+ // base60 almost not used, no needs to optimize
+ return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
+}
+
+function constructYamlInteger(data: string): number {
+ let value = data;
+ const digits: number[] = [];
+
+ if (value.indexOf("_") !== -1) {
+ value = value.replace(/_/g, "");
+ }
+
+ let sign = 1;
+ let ch = value[0];
+ if (ch === "-" || ch === "+") {
+ if (ch === "-") sign = -1;
+ value = value.slice(1);
+ ch = value[0];
+ }
+
+ if (value === "0") return 0;
+
+ if (ch === "0") {
+ if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
+ if (value[1] === "x") return sign * parseInt(value, 16);
+ return sign * parseInt(value, 8);
+ }
+
+ if (value.indexOf(":") !== -1) {
+ value.split(":").forEach((v): void => {
+ digits.unshift(parseInt(v, 10));
+ });
+
+ let valueInt = 0;
+ let base = 1;
+
+ digits.forEach((d): void => {
+ valueInt += d * base;
+ base *= 60;
+ });
+
+ return sign * valueInt;
+ }
+
+ return sign * parseInt(value, 10);
+}
+
+function isInteger(object: Any): boolean {
+ return (
+ Object.prototype.toString.call(object) === "[object Number]" &&
+ object % 1 === 0 &&
+ !isNegativeZero(object)
+ );
+}
+
+export const int = new Type("tag:yaml.org,2002:int", {
+ construct: constructYamlInteger,
+ defaultStyle: "decimal",
+ kind: "scalar",
+ predicate: isInteger,
+ represent: {
+ binary(obj: number): string {
+ return obj >= 0
+ ? `0b${obj.toString(2)}`
+ : `-0b${obj.toString(2).slice(1)}`;
+ },
+ octal(obj: number): string {
+ return obj >= 0 ? `0${obj.toString(8)}` : `-0${obj.toString(8).slice(1)}`;
+ },
+ decimal(obj: number): string {
+ return obj.toString(10);
+ },
+ hexadecimal(obj: number): string {
+ return obj >= 0
+ ? `0x${obj.toString(16).toUpperCase()}`
+ : `-0x${obj
+ .toString(16)
+ .toUpperCase()
+ .slice(1)}`;
+ }
+ },
+ resolve: resolveYamlInteger,
+ styleAliases: {
+ binary: [2, "bin"],
+ decimal: [10, "dec"],
+ hexadecimal: [16, "hex"],
+ octal: [8, "oct"]
+ }
+});
diff --git a/std/encoding/yaml/type/map.ts b/std/encoding/yaml/type/map.ts
new file mode 100644
index 000000000..6d273254d
--- /dev/null
+++ b/std/encoding/yaml/type/map.ts
@@ -0,0 +1,14 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+export const map = new Type("tag:yaml.org,2002:map", {
+ construct(data): Any {
+ return data !== null ? data : {};
+ },
+ kind: "mapping"
+});
diff --git a/std/encoding/yaml/type/merge.ts b/std/encoding/yaml/type/merge.ts
new file mode 100644
index 000000000..9389a0d20
--- /dev/null
+++ b/std/encoding/yaml/type/merge.ts
@@ -0,0 +1,15 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+
+function resolveYamlMerge(data: string): boolean {
+ return data === "<<" || data === null;
+}
+
+export const merge = new Type("tag:yaml.org,2002:merge", {
+ kind: "scalar",
+ resolve: resolveYamlMerge
+});
diff --git a/std/encoding/yaml/type/mod.ts b/std/encoding/yaml/type/mod.ts
new file mode 100644
index 000000000..1970753df
--- /dev/null
+++ b/std/encoding/yaml/type/mod.ts
@@ -0,0 +1,18 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+export { binary } from "./binary.ts";
+export { bool } from "./bool.ts";
+export { float } from "./float.ts";
+export { int } from "./int.ts";
+export { map } from "./map.ts";
+export { merge } from "./merge.ts";
+export { nil } from "./nil.ts";
+export { omap } from "./omap.ts";
+export { pairs } from "./pairs.ts";
+export { seq } from "./seq.ts";
+export { set } from "./set.ts";
+export { str } from "./str.ts";
+export { timestamp } from "./timestamp.ts";
diff --git a/std/encoding/yaml/type/nil.ts b/std/encoding/yaml/type/nil.ts
new file mode 100644
index 000000000..c7e87f96d
--- /dev/null
+++ b/std/encoding/yaml/type/nil.ts
@@ -0,0 +1,45 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+
+function resolveYamlNull(data: string): boolean {
+ const max = data.length;
+
+ return (
+ (max === 1 && data === "~") ||
+ (max === 4 && (data === "null" || data === "Null" || data === "NULL"))
+ );
+}
+
+function constructYamlNull(): null {
+ return null;
+}
+
+function isNull(object: unknown): object is null {
+ return object === null;
+}
+
+export const nil = new Type("tag:yaml.org,2002:null", {
+ construct: constructYamlNull,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isNull,
+ represent: {
+ canonical(): string {
+ return "~";
+ },
+ lowercase(): string {
+ return "null";
+ },
+ uppercase(): string {
+ return "NULL";
+ },
+ camelcase(): string {
+ return "Null";
+ }
+ },
+ resolve: resolveYamlNull
+});
diff --git a/std/encoding/yaml/type/omap.ts b/std/encoding/yaml/type/omap.ts
new file mode 100644
index 000000000..1b7a79a50
--- /dev/null
+++ b/std/encoding/yaml/type/omap.ts
@@ -0,0 +1,46 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+const _hasOwnProperty = Object.prototype.hasOwnProperty;
+const _toString = Object.prototype.toString;
+
+function resolveYamlOmap(data: Any): boolean {
+ const objectKeys: string[] = [];
+ let pairKey = "";
+ let pairHasKey = false;
+
+ for (const pair of data) {
+ pairHasKey = false;
+
+ if (_toString.call(pair) !== "[object Object]") return false;
+
+ for (pairKey in pair) {
+ if (_hasOwnProperty.call(pair, pairKey)) {
+ if (!pairHasKey) pairHasKey = true;
+ else return false;
+ }
+ }
+
+ if (!pairHasKey) return false;
+
+ if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
+ else return false;
+ }
+
+ return true;
+}
+
+function constructYamlOmap(data: Any): Any {
+ return data !== null ? data : [];
+}
+
+export const omap = new Type("tag:yaml.org,2002:omap", {
+ construct: constructYamlOmap,
+ kind: "sequence",
+ resolve: resolveYamlOmap
+});
diff --git a/std/encoding/yaml/type/pairs.ts b/std/encoding/yaml/type/pairs.ts
new file mode 100644
index 000000000..37f8eb630
--- /dev/null
+++ b/std/encoding/yaml/type/pairs.ts
@@ -0,0 +1,49 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+const _toString = Object.prototype.toString;
+
+function resolveYamlPairs(data: Any[][]): boolean {
+ const result = new Array(data.length);
+
+ for (let index = 0; index < data.length; index++) {
+ const pair = data[index];
+
+ if (_toString.call(pair) !== "[object Object]") return false;
+
+ const keys = Object.keys(pair);
+
+ if (keys.length !== 1) return false;
+
+ result[index] = [keys[0], pair[keys[0] as Any]];
+ }
+
+ return true;
+}
+
+function constructYamlPairs(data: string): Any[] {
+ if (data === null) return [];
+
+ const result = new Array(data.length);
+
+ for (let index = 0; index < data.length; index += 1) {
+ const pair = data[index];
+
+ const keys = Object.keys(pair);
+
+ result[index] = [keys[0], pair[keys[0] as Any]];
+ }
+
+ return result;
+}
+
+export const pairs = new Type("tag:yaml.org,2002:pairs", {
+ construct: constructYamlPairs,
+ kind: "sequence",
+ resolve: resolveYamlPairs
+});
diff --git a/std/encoding/yaml/type/seq.ts b/std/encoding/yaml/type/seq.ts
new file mode 100644
index 000000000..32c700b6e
--- /dev/null
+++ b/std/encoding/yaml/type/seq.ts
@@ -0,0 +1,14 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+export const seq = new Type("tag:yaml.org,2002:seq", {
+ construct(data): Any {
+ return data !== null ? data : [];
+ },
+ kind: "sequence"
+});
diff --git a/std/encoding/yaml/type/set.ts b/std/encoding/yaml/type/set.ts
new file mode 100644
index 000000000..3273223f7
--- /dev/null
+++ b/std/encoding/yaml/type/set.ts
@@ -0,0 +1,31 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+import { Any } from "../utils.ts";
+
+const _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function resolveYamlSet(data: Any): boolean {
+ if (data === null) return true;
+
+ for (const key in data) {
+ if (_hasOwnProperty.call(data, key)) {
+ if (data[key] !== null) return false;
+ }
+ }
+
+ return true;
+}
+
+function constructYamlSet(data: string): Any {
+ return data !== null ? data : {};
+}
+
+export const set = new Type("tag:yaml.org,2002:set", {
+ construct: constructYamlSet,
+ kind: "mapping",
+ resolve: resolveYamlSet
+});
diff --git a/std/encoding/yaml/type/str.ts b/std/encoding/yaml/type/str.ts
new file mode 100644
index 000000000..8c24e9398
--- /dev/null
+++ b/std/encoding/yaml/type/str.ts
@@ -0,0 +1,12 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+
+export const str = new Type("tag:yaml.org,2002:str", {
+ construct(data): string {
+ return data !== null ? data : "";
+ },
+ kind: "scalar"
+});
diff --git a/std/encoding/yaml/type/timestamp.ts b/std/encoding/yaml/type/timestamp.ts
new file mode 100644
index 000000000..38cc9d940
--- /dev/null
+++ b/std/encoding/yaml/type/timestamp.ts
@@ -0,0 +1,96 @@
+// Ported from js-yaml v3.13.1:
+// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
+// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+import { Type } from "../type.ts";
+
+const YAML_DATE_REGEXP = new RegExp(
+ "^([0-9][0-9][0-9][0-9])" + // [1] year
+ "-([0-9][0-9])" + // [2] month
+ "-([0-9][0-9])$" // [3] day
+);
+
+const YAML_TIMESTAMP_REGEXP = new RegExp(
+ "^([0-9][0-9][0-9][0-9])" + // [1] year
+ "-([0-9][0-9]?)" + // [2] month
+ "-([0-9][0-9]?)" + // [3] day
+ "(?:[Tt]|[ \\t]+)" + // ...
+ "([0-9][0-9]?)" + // [4] hour
+ ":([0-9][0-9])" + // [5] minute
+ ":([0-9][0-9])" + // [6] second
+ "(?:\\.([0-9]*))?" + // [7] fraction
+ "(?:[ \\t]*(Z|([-+])([0-9][0-9]?)" + // [8] tz [9] tz_sign [10] tz_hour
+ "(?::([0-9][0-9]))?))?$" // [11] tz_minute
+);
+
+function resolveYamlTimestamp(data: string): boolean {
+ if (data === null) return false;
+ if (YAML_DATE_REGEXP.exec(data) !== null) return true;
+ if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
+ return false;
+}
+
+function constructYamlTimestamp(data: string): Date {
+ let match = YAML_DATE_REGEXP.exec(data);
+ if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
+
+ if (match === null) throw new Error("Date resolve error");
+
+ // match: [1] year [2] month [3] day
+
+ const year = +match[1];
+ const month = +match[2] - 1; // JS month starts with 0
+ const day = +match[3];
+
+ if (!match[4]) {
+ // no hour
+ return new Date(Date.UTC(year, month, day));
+ }
+
+ // match: [4] hour [5] minute [6] second [7] fraction
+
+ const hour = +match[4];
+ const minute = +match[5];
+ const second = +match[6];
+
+ let fraction = 0;
+ if (match[7]) {
+ let partFraction = match[7].slice(0, 3);
+ while (partFraction.length < 3) {
+ // milli-seconds
+ partFraction += "0";
+ }
+ fraction = +partFraction;
+ }
+
+ // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute
+
+ let delta = null;
+ if (match[9]) {
+ const tzHour = +match[10];
+ const tzMinute = +(match[11] || 0);
+ delta = (tzHour * 60 + tzMinute) * 60000; // delta in mili-seconds
+ if (match[9] === "-") delta = -delta;
+ }
+
+ const date = new Date(
+ Date.UTC(year, month, day, hour, minute, second, fraction)
+ );
+
+ if (delta) date.setTime(date.getTime() - delta);
+
+ return date;
+}
+
+function representYamlTimestamp(date: Date): string {
+ return date.toISOString();
+}
+
+export const timestamp = new Type("tag:yaml.org,2002:timestamp", {
+ construct: constructYamlTimestamp,
+ instanceOf: Date,
+ kind: "scalar",
+ represent: representYamlTimestamp,
+ resolve: resolveYamlTimestamp
+});