From 0fea87f8f248f8c39020a97ee9e097f128a6c651 Mon Sep 17 00:00:00 2001 From: George Fu Date: Fri, 21 Jun 2024 15:44:39 +0000 Subject: [PATCH] stack based encoding --- .../core/src/submodules/cbor/cbor-encode.ts | 47 ++++++++++++------- .../core/src/submodules/cbor/cbor.spec.ts | 8 ++-- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/core/src/submodules/cbor/cbor-encode.ts b/packages/core/src/submodules/cbor/cbor-encode.ts index 892b25d2e4b..c9cf836ffa5 100644 --- a/packages/core/src/submodules/cbor/cbor-encode.ts +++ b/packages/core/src/submodules/cbor/cbor-encode.ts @@ -83,14 +83,21 @@ function encodeHeader(major: CborMajorType, value: Uint64 | number): void { } } +const headerEncode: Symbol = Symbol("headerEncodeCbor"); + /** * @param _input - JS data object. */ export function encode(_input: any): void { - const encodeQueue = [_input]; + const encodeStack = [_input]; + + while (encodeStack.length) { + const input = encodeStack.pop(); + if (input?.headerEncode === headerEncode) { + encodeHeader(input.major, input.count); + continue; + } - while (encodeQueue.length) { - const input = encodeQueue.shift(); ensureSpace(typeof input === "string" ? input.length * 4 : 64); if (typeof input === "string") { @@ -172,11 +179,14 @@ export function encode(_input: any): void { // though the CBOR spec includes it. throw new Error("@smithy/core/cbor: client may not serialize undefined value."); } else if (Array.isArray(input)) { - encodeHeader(majorList, input.length); - for (let i = 0; i < input.length; ++i) { - // encode(input[i]); - encodeQueue.push(input[i]); + for (let i = input.length - 1; i >= 0; --i) { + encodeStack.push(input[i]); } + encodeStack.push({ + headerEncode, + major: majorList, + count: input.length, + }); continue; } else if (typeof input.byteLength === "number") { ensureSpace(input.length * 2); @@ -185,20 +195,25 @@ export function encode(_input: any): void { cursor += input.byteLength; continue; } else if (typeof input === "object" && "tag" in input && "value" in input && Object.keys(input).length === 2) { - encodeHeader(majorTag, input.tag); - // encode(input.value); - encodeQueue.push(input.value); + encodeStack.push(input.value); + encodeStack.push({ + headerEncode, + major: majorTag, + count: input.tag, + }); continue; } else if (typeof input === "object") { const keys = Object.keys(input); - encodeHeader(majorMap, keys.length); - for (let i = 0; i < keys.length; ++i) { + for (let i = keys.length - 1; i >= 0; --i) { const key = keys[i]; - // encode(key); - // encode(input[key]); - encodeQueue.push(key); - encodeQueue.push(input[key]); + encodeStack.push(input[key]); + encodeStack.push(key); } + encodeStack.push({ + headerEncode, + major: majorMap, + count: keys.length, + }); continue; } diff --git a/packages/core/src/submodules/cbor/cbor.spec.ts b/packages/core/src/submodules/cbor/cbor.spec.ts index 3e1bf157678..d0532475625 100644 --- a/packages/core/src/submodules/cbor/cbor.spec.ts +++ b/packages/core/src/submodules/cbor/cbor.spec.ts @@ -192,10 +192,10 @@ describe("cbor", () => { }, cbor: allocByteArray([ 164, 102, 110, 117, 109, 98, 101, 114, 27, 0, 0, 122, 204, 161, 196, 74, 227, 103, 109, 101, 115, 115, 97, 103, - 101, 108, 104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 100, 108, 105, 115, 116, 131, 99, 109, 97, - 112, 163, +0, +244, +161, 97, 97, 97, 97, 97, 98, 97, 98, 101, 105, 116, 101, 109, 115, 136, +97, +97, +97, +98, - 0, 32, 245, 244, 246, 96, 100, 116, 101, 115, 116, 130, 109, 110, 101, 115, 116, 101, 100, 32, 105, 116, 101, - 109, 32, 65, 109, 110, 101, 115, 116, 101, 100, 32, 105, 116, 101, 109, 32, 66, + 101, 108, 104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 100, 108, 105, 115, 116, 131, 0, 244, 161, + 97, 97, 97, 98, 99, 109, 97, 112, 163, 97, 97, 97, 97, 97, 98, 97, 98, 101, 105, 116, 101, 109, 115, 136, 0, 32, + 245, 244, 246, 96, 100, 116, 101, 115, 116, 130, 109, 110, 101, 115, 116, 101, 100, 32, 105, 116, 101, 109, 32, + 65, 109, 110, 101, 115, 116, 101, 100, 32, 105, 116, 101, 109, 32, 66, ]), }, ];