From bed8a4a51f424e5ead73aa4e5fdf855eeb760de0 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 9 Apr 2024 19:04:43 +0200 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20use=20published=20js?= =?UTF-8?q?on-pack=20and=20base64=20packages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + src/index.ts | 5 +- src/json-binary/README.md | 18 - src/json-binary/__tests__/automated.spec.ts | 12 - src/json-binary/__tests__/stringify.spec.ts | 24 - src/json-binary/codec.ts | 124 ---- src/json-binary/constants.ts | 4 - src/json-binary/index.ts | 4 +- src/json-binary/types.ts | 20 - src/json-brand/README.md | 12 - src/json-brand/global.d.ts | 7 - src/json-brand/index.d.ts | 10 - src/json-brand/index.ts | 6 +- src/json-brand/types.ts | 9 - src/json-cli/json-pack.ts | 6 +- src/json-cli/json-unpack.ts | 4 +- src/json-clone/cloneBinary.ts | 2 +- src/json-crdt-patch/PatchBuilder.ts | 2 +- .../__demos__/PatchBuilder-operations.ts | 2 +- src/json-crdt-patch/codec/binary/Decoder.ts | 2 +- src/json-crdt-patch/codec/binary/Encoder.ts | 2 +- .../codec/compact-binary/decode.ts | 2 +- .../codec/compact-binary/encode.ts | 2 +- src/json-crdt-patch/codec/compact/decode.ts | 2 +- src/json-crdt-patch/codec/compact/encode.ts | 2 +- src/json-crdt-patch/codec/verbose/decode.ts | 2 +- src/json-crdt-patch/codec/verbose/encode.ts | 2 +- src/json-crdt-patch/util/binary/CrdtReader.ts | 2 +- src/json-crdt-patch/util/binary/CrdtWriter.ts | 2 +- .../__bench__/util/concurrent-trace.ts | 4 +- src/json-crdt/__bench__/util/fuzzer-traces.ts | 4 +- src/json-crdt/codec/indexed/binary/Decoder.ts | 2 +- src/json-crdt/codec/indexed/binary/Encoder.ts | 2 +- src/json-crdt/codec/sidecar/binary/Decoder.ts | 2 +- src/json-crdt/codec/sidecar/binary/Encoder.ts | 4 +- .../sidecar/binary/__tests__/Encoder.spec.ts | 2 +- .../__tests__/all-types-smoketest.spec.ts | 2 +- .../__tests__/automated-logical.spec.ts | 2 +- .../binary/__tests__/fuzzer-logical.spec.ts | 2 +- .../codec/structural/binary/Decoder.ts | 2 +- .../codec/structural/binary/Encoder.ts | 2 +- .../codec/structural/binary/ViewDecoder.ts | 2 +- .../structural/compact-binary/Decoder.ts | 2 +- .../structural/compact-binary/Encoder.ts | 2 +- .../codec/structural/verbose/Decoder.ts | 2 +- .../codec/structural/verbose/Encoder.ts | 2 +- src/json-crdt/history/LocalHistoryCrud.ts | 4 +- src/json-crdt/log/codec/LogDecoder.ts | 4 +- src/json-crdt/log/codec/LogEncoder.ts | 4 +- .../log/codec/__tests__/LogEncoder.spec.ts | 4 +- src/json-crdt/log/codec/logDecoderOpts.ts | 4 +- src/json-crdt/log/codec/logEncoderOpts.ts | 6 +- src/json-crdt/nodes/rga/AbstractRga.ts | 4 +- .../schema/__tests__/toSchema.spec.ts | 2 +- src/json-equal/$$deepEqual/v1.ts | 2 +- src/json-expression/codegen.ts | 4 +- src/json-hash/index.ts | 2 +- src/json-pack/JsonPackExtension.ts | 14 - src/json-pack/JsonPackValue.ts | 13 - src/json-pack/README.md | 426 ----------- .../__bench__/bench.bson.encoding.ts | 49 -- .../__bench__/bench.cbor-dag.encoding.ts | 57 -- .../__bench__/bench.cbor.decoding.ts | 59 -- .../__bench__/bench.cbor.encoding.ts | 58 -- src/json-pack/__bench__/bench.encoders.ts | 84 --- .../__bench__/bench.encoding.cbor.ts | 77 -- src/json-pack/__bench__/bench.encoding.ts | 139 ---- src/json-pack/__bench__/bench.ion.encoding.ts | 48 -- .../__bench__/bench.json.decoding.ts | 47 -- .../__bench__/bench.json.encoding.ts | 53 -- .../__bench__/bench.msgpack.decoding.ts | 82 --- .../__bench__/bench.msgpack.encoding.ts | 73 -- .../__bench__/bench.resp.decoding.ts | 70 -- .../__bench__/bench.resp.encoding.ts | 52 -- src/json-pack/__bench__/bench.shallow-read.ts | 118 --- src/json-pack/__bench__/bench.slice.ts | 36 - .../__bench__/bench.ubjson.decoding.ts | 44 -- .../__bench__/bench.ubjson.encoding.ts | 37 - src/json-pack/__bench__/bench.writer-size.ts | 71 -- .../__bench__/profiler/cbor-decoding.ts | 20 - src/json-pack/__bench__/profiler/slices.ts | 69 -- src/json-pack/__bench__/profiler/time.ts | 31 - src/json-pack/__bench__/profiler/truncate.ts | 37 - src/json-pack/__demos__/cbor.ts | 63 -- src/json-pack/__demos__/json.ts | 38 - src/json-pack/__demos__/msgpack.ts | 45 -- src/json-pack/__demos__/ubjson.ts | 38 - src/json-pack/bencode/BencodeDecoder.ts | 151 ---- src/json-pack/bencode/BencodeEncoder.ts | 164 ----- src/json-pack/bencode/README.md | 22 - .../bencode/__tests__/BencodeDecoder.spec.ts | 271 ------- .../bencode/__tests__/BencodeEncoder.spec.ts | 205 ------ .../bencode/__tests__/automated.spec.ts | 42 -- src/json-pack/bencode/types.ts | 1 - src/json-pack/bson/BsonEncoder.ts | 381 ---------- src/json-pack/bson/README.md | 56 -- .../bson/__tests__/BsonEncoder-values.spec.ts | 154 ---- .../bson/__tests__/BsonEncoder.spec.ts | 258 ------- src/json-pack/bson/__tests__/codec.spec.ts | 23 - src/json-pack/bson/index.ts | 2 - src/json-pack/bson/values.ts | 63 -- src/json-pack/cbor/CborDecoder.ts | 408 ----------- src/json-pack/cbor/CborDecoderBase.ts | 348 --------- src/json-pack/cbor/CborDecoderDag.ts | 9 - src/json-pack/cbor/CborEncoder.ts | 71 -- src/json-pack/cbor/CborEncoderDag.ts | 18 - src/json-pack/cbor/CborEncoderFast.ts | 333 --------- src/json-pack/cbor/CborEncoderStable.ts | 68 -- src/json-pack/cbor/README.md | 490 ------------- .../__tests__/CborDecoder.readLevel.spec.ts | 75 -- .../CborDecoder.shallow-reading.spec.ts | 183 ----- .../cbor/__tests__/CborDecoder.spec.ts | 408 ----------- .../__tests__/CborDecoder.validate.spec.ts | 55 -- .../cbor/__tests__/CborDecoderDag.spec.ts | 55 -- .../cbor/__tests__/CborEncoder.spec.ts | 413 ----------- .../cbor/__tests__/CborEncoderDag.spec.ts | 115 --- .../cbor/__tests__/CborEncoderStable.spec.ts | 227 ------ .../cbor/__tests__/cbor-js-testcases.ts | 101 --- src/json-pack/cbor/__tests__/cbor-js.spec.ts | 45 -- src/json-pack/cbor/__tests__/codec.spec.ts | 72 -- src/json-pack/cbor/__tests__/fuzzing.spec.ts | 50 -- .../shallow-read.genShallowRead.spec.ts | 132 ---- src/json-pack/cbor/constants.ts | 42 -- src/json-pack/cbor/shared.ts | 11 - src/json-pack/cbor/types.ts | 1 - src/json-pack/codecs/Codecs.ts | 16 - src/json-pack/codecs/cbor.ts | 17 - src/json-pack/codecs/json.ts | 17 - src/json-pack/codecs/msgpack.ts | 17 - src/json-pack/codecs/types.ts | 9 - src/json-pack/constants.ts | 5 - src/json-pack/ion/Import.ts | 49 -- src/json-pack/ion/IonEncoderFast.ts | 234 ------ src/json-pack/ion/README.md | 59 -- src/json-pack/ion/__tests__/Import.spec.ts | 47 -- .../ion/__tests__/IonEncoder.spec.ts | 212 ------ src/json-pack/ion/__tests__/automated.spec.ts | 15 - src/json-pack/ion/ast.ts | 185 ----- src/json-pack/ion/constants.ts | 25 - src/json-pack/ion/symbols.ts | 16 - src/json-pack/ion/types.ts | 1 - src/json-pack/json/JsonDecoder.ts | 683 ------------------ src/json-pack/json/JsonDecoderDag.ts | 133 ---- src/json-pack/json/JsonEncoder.ts | 282 -------- src/json-pack/json/JsonEncoderDag.ts | 59 -- src/json-pack/json/JsonEncoderStable.ts | 23 - src/json-pack/json/README.md | 117 --- .../json/__tests__/JsonDecoder.spec.ts | 440 ----------- .../json/__tests__/JsonDecoderDag.spec.ts | 72 -- .../json/__tests__/JsonEncoder.spec.ts | 182 ----- .../json/__tests__/JsonEncoderDag.spec.ts | 63 -- .../json/__tests__/automated.spec.ts | 39 - src/json-pack/json/__tests__/fuzzer.spec.ts | 34 - .../json/__tests__/memory-leaks.spec.ts | 37 - src/json-pack/json/types.ts | 1 - src/json-pack/json/util.ts | 13 - src/json-pack/msgpack/MsgPackDecoder.ts | 256 ------- src/json-pack/msgpack/MsgPackDecoderFast.ts | 181 ----- src/json-pack/msgpack/MsgPackEncoder.ts | 39 - src/json-pack/msgpack/MsgPackEncoderFast.ts | 324 --------- src/json-pack/msgpack/MsgPackEncoderStable.ts | 18 - .../msgpack/MsgPackToJsonConverter.ts | 241 ------ src/json-pack/msgpack/README.md | 143 ---- .../MsgPackDecoder.one-level.spec.ts | 311 -------- .../MsgPackDecoder.shallow-reading.spec.ts | 172 ----- .../__tests__/MsgPackDecoder.validate.spec.ts | 25 - .../__tests__/MsgPackDecoderFast.spec.ts | 301 -------- .../__tests__/MsgPackEncoder.codec.spec.ts | 89 --- .../msgpack/__tests__/MsgPackEncoder.spec.ts | 68 -- .../MsgPackEncoderFast.overwrite.spec.ts | 16 - .../__tests__/MsgPackEncoderFast.spec.ts | 293 -------- .../__tests__/MsgPackEncoderStable.spec.ts | 27 - .../__tests__/MsgPackToJsonConverter.spec.ts | 15 - src/json-pack/msgpack/__tests__/codec.spec.ts | 15 - .../msgpack/__tests__/decode.spec.ts | 239 ------ .../msgpack/__tests__/fuzzing.spec.ts | 19 - .../msgpack/__tests__/numbers.spec.ts | 80 -- .../shallow-read.genShallowRead.spec.ts | 130 ---- src/json-pack/msgpack/constants.ts | 6 - src/json-pack/msgpack/index.ts | 38 - src/json-pack/msgpack/shallow-read.ts | 113 --- src/json-pack/msgpack/types.ts | 15 - src/json-pack/msgpack/util.ts | 14 - src/json-pack/resp/README.md | 1 - src/json-pack/resp/RespDecoder.ts | 422 ----------- src/json-pack/resp/RespEncoder.ts | 503 ------------- src/json-pack/resp/RespEncoderLegacy.ts | 96 --- src/json-pack/resp/RespStreamingDecoder.ts | 114 --- .../resp/__tests__/RespDecoder.spec.ts | 235 ------ .../resp/__tests__/RespEncoder.spec.ts | 355 --------- .../resp/__tests__/RespEncoderLegacy.spec.ts | 52 -- .../__tests__/RespStreamingDecoder.spec.ts | 77 -- src/json-pack/resp/__tests__/codec.spec.ts | 43 -- src/json-pack/resp/__tests__/fuzzing.spec.ts | 17 - src/json-pack/resp/__tests__/skipping.spec.ts | 41 -- src/json-pack/resp/constants.ts | 27 - src/json-pack/resp/extensions.ts | 19 - src/json-pack/resp/index.ts | 6 - src/json-pack/types.ts | 59 -- src/json-pack/ubjson/README.md | 184 ----- src/json-pack/ubjson/UbjsonDecoder.ts | 124 ---- src/json-pack/ubjson/UbjsonEncoder.ts | 231 ------ .../ubjson/__tests__/UbjsonDecoder.spec.ts | 198 ----- .../ubjson/__tests__/UbjsonEncoder.spec.ts | 183 ----- .../ubjson/__tests__/automated.spec.ts | 35 - src/json-pack/ubjson/__tests__/fuzzer.spec.ts | 41 -- src/json-pack/util/CompressionTable.ts | 167 ----- src/json-pack/util/DecompressionTable.ts | 89 --- .../util/__tests__/CompressionTable.spec.ts | 69 -- .../util/__tests__/DecompressionTable.spec.ts | 41 -- src/json-pack/util/objKeyCmp.ts | 5 - src/json-patch/codec/binary/Decoder.ts | 4 +- src/json-patch/codec/binary/Encoder.ts | 2 +- .../binary/__tests__/message-pack.spec.ts | 2 +- src/json-patch/op/AbstractOp.ts | 2 +- src/json-patch/op/OpAdd.ts | 2 +- src/json-patch/op/OpAnd.ts | 2 +- src/json-patch/op/OpContains.ts | 2 +- src/json-patch/op/OpCopy.ts | 2 +- src/json-patch/op/OpDefined.ts | 2 +- src/json-patch/op/OpEnds.ts | 2 +- src/json-patch/op/OpExtend.ts | 2 +- src/json-patch/op/OpFlip.ts | 2 +- src/json-patch/op/OpIn.ts | 2 +- src/json-patch/op/OpInc.ts | 2 +- src/json-patch/op/OpLess.ts | 2 +- src/json-patch/op/OpMatches.ts | 2 +- src/json-patch/op/OpMerge.ts | 2 +- src/json-patch/op/OpMore.ts | 2 +- src/json-patch/op/OpMove.ts | 2 +- src/json-patch/op/OpNot.ts | 2 +- src/json-patch/op/OpOr.ts | 2 +- src/json-patch/op/OpRemove.ts | 2 +- src/json-patch/op/OpReplace.ts | 2 +- src/json-patch/op/OpSplit.ts | 2 +- src/json-patch/op/OpStarts.ts | 2 +- src/json-patch/op/OpStrDel.ts | 2 +- src/json-patch/op/OpStrIns.ts | 2 +- src/json-patch/op/OpTest.ts | 2 +- src/json-patch/op/OpTestString.ts | 2 +- src/json-patch/op/OpTestStringLen.ts | 2 +- src/json-patch/op/OpTestType.ts | 2 +- src/json-patch/op/OpType.ts | 2 +- src/json-patch/op/OpUndefined.ts | 2 +- src/json-random/RandomJson.ts | 2 +- src/json-size/__tests__/fuzz.spec.ts | 2 +- .../__tests__/msgpackSizeFast.spec.ts | 2 +- src/json-size/__tests__/testJsonSize.ts | 2 +- src/json-size/json.ts | 2 +- src/json-size/msgpackSizeFast.ts | 4 +- src/json-stable/index.ts | 2 +- src/json-type-cli/Cli.ts | 2 +- src/json-type-cli/codecs/cbor.ts | 6 +- src/json-type-cli/codecs/json.ts | 6 +- src/json-type-cli/codecs/json2.ts | 8 +- src/json-type-cli/codecs/json4.ts | 8 +- src/json-type-cli/codecs/msgpack.ts | 6 +- src/json-type-cli/codecs/ubjson.ts | 6 +- src/json-type-cli/defaultCodecs.ts | 2 +- src/json-type-cli/params/CliParamCmd.ts | 4 +- src/json-type-value/Value.ts | 2 +- src/json-type/__demos__/json-type.ts | 2 +- .../binary/BinaryEncoderCodegenContext.ts | 4 +- .../binary/CborEncoderCodegenContext.ts | 2 +- .../binary/JsonEncoderCodegenContext.ts | 2 +- .../MessagePackEncoderCodegenContext.ts | 2 +- .../CborEncoderCodegenContext.spec.ts | 8 +- .../JsonEncoderCodegenContext.spec.ts | 6 +- .../MessagePackEncoderCodegenContext.spec.ts | 8 +- .../json/JsonTextEncoderCodegenContext.ts | 4 +- src/json-type/codegen/types.ts | 2 +- src/json-type/type/classes/AbstractType.ts | 14 +- src/json-type/type/classes/AnyType.ts | 6 +- src/json-type/type/classes/ArrayType.ts | 4 +- src/json-type/type/classes/BinaryType.ts | 4 +- src/json-type/type/classes/BooleanType.ts | 4 +- src/json-type/type/classes/ConstType.ts | 4 +- src/json-type/type/classes/MapType.ts | 6 +- src/json-type/type/classes/NumberType.ts | 4 +- src/json-type/type/classes/ObjectType.ts | 6 +- src/json-type/type/classes/OrType.ts | 4 +- src/json-type/type/classes/RefType.ts | 6 +- src/json-type/type/classes/StringType.ts | 6 +- src/json-type/type/classes/TupleType.ts | 2 +- src/json-type/typescript/toText.ts | 2 +- .../e2e/uws/http/FetchRpcClient.spec.ts | 6 +- .../e2e/uws/http/StreamingRpcClient.spec.ts | 6 +- .../e2e/uws/ws/RpcPersistentClient.spec.ts | 6 +- .../browser/createBinaryWsRpcClient.ts | 4 +- .../browser/createJsonWsRpcClient.ts | 4 +- src/reactive-rpc/common/channel/channel.ts | 2 +- src/reactive-rpc/common/channel/mock.ts | 2 +- src/reactive-rpc/common/codec/RpcCodec.ts | 2 +- src/reactive-rpc/common/codec/RpcCodecs.ts | 2 +- .../codec/binary/BinaryRpcMessageCodec.ts | 4 +- .../__tests__/BinaryRpcMessageCodec.spec.ts | 4 +- .../codec/binary/__tests__/automated.spec.ts | 4 +- .../codec/binary/__tests__/decode.spec.ts | 8 +- .../codec/binary/__tests__/encode.spec.ts | 4 +- .../binary/__tests__/smoke-tests.spec.ts | 4 +- .../common/codec/binary/decode.ts | 4 +- .../codec/compact/CompactRpcMessageCodec.ts | 8 +- .../__tests__/CompactRpcMessageCodec.spec.ts | 4 +- .../codec/compact/__tests__/automated.spec.ts | 4 +- .../compact/__tests__/smoke-tests.spec.ts | 4 +- .../json-rpc-2/JsonRpc2RpcMessageCodec.ts | 8 +- .../json-rpc-2/__tests__/automated.spec.ts | 4 +- src/reactive-rpc/common/codec/types.ts | 2 +- src/reactive-rpc/common/messages/messages.ts | 10 +- src/reactive-rpc/common/messages/types.ts | 2 +- .../rpc/__tests__/RpcPersistentClient.spec.ts | 4 +- .../error/__tests__/RpcErrorType.spec.ts | 4 +- .../rpc/client/EncodedStaticRpcClient.ts | 2 +- .../common/rpc/client/FetchRpcClient.ts | 2 +- .../common/testing/buildE2eClient.ts | 4 +- src/reactive-rpc/server/context.ts | 6 +- src/reactive-rpc/server/http1/Http1Server.ts | 4 +- src/reactive-rpc/server/http1/context.ts | 4 +- src/reactive-rpc/server/uws/RpcApp.ts | 8 +- .../server/ws/codec/WsFrameDecoder.ts | 2 +- .../server/ws/codec/WsFrameEncoder.ts | 4 +- .../server/ws/server/WsServerConnection.ts | 4 +- .../__tests__/WsServerConnection.spec.ts | 4 +- src/util/base64/README.md | 91 --- src/util/base64/__bench__/decode.js | 77 -- src/util/base64/__bench__/encode.js | 98 --- .../base64/__tests__/decode-base64url.spec.ts | 20 - src/util/base64/__tests__/decode-bin.spec.ts | 31 - src/util/base64/__tests__/decode.spec.ts | 33 - .../base64/__tests__/encode-base64url.spec.ts | 23 - src/util/base64/__tests__/encode-bin.spec.ts | 38 - src/util/base64/__tests__/encode.spec.ts | 24 - src/util/base64/constants.ts | 2 - src/util/base64/createFromBase64.ts | 66 -- src/util/base64/createFromBase64Bin.ts | 73 -- src/util/base64/createToBase64.ts | 45 -- src/util/base64/createToBase64Bin.ts | 58 -- src/util/base64/createToBase64BinUint8.ts | 56 -- src/util/base64/fromBase64.ts | 10 - src/util/base64/fromBase64Bin.ts | 3 - src/util/base64/fromBase64Url.ts | 3 - src/util/base64/index.ts | 7 - src/util/base64/toBase64.ts | 12 - src/util/base64/toBase64Bin.ts | 3 - src/util/base64/toBase64Url.ts | 3 - src/util/buffers/Reader.ts | 105 --- src/util/buffers/Slice.ts | 12 - src/util/buffers/StreamingOctetReader.ts | 175 ----- src/util/buffers/StreamingReader.ts | 179 ----- src/util/buffers/Uint8ArrayCut.ts | 7 - src/util/buffers/Writer.ts | 269 ------- .../buffers/__bench__/bench.decodeUtf8.ts | 108 --- .../buffers/__tests__/StreamingReader.spec.ts | 57 -- src/util/buffers/__tests__/isFloat32.spec.ts | 9 - src/util/buffers/b.ts | 1 - src/util/buffers/bufferToUint8Array.ts | 1 - src/util/buffers/cmpUint8Array.ts | 6 - src/util/buffers/cmpUint8Array2.ts | 18 - src/util/buffers/cmpUint8Array3.ts | 19 - src/util/buffers/concat.ts | 31 - src/util/buffers/copy.ts | 5 - src/util/buffers/f16.ts | 16 - src/util/buffers/index.ts | 2 +- src/util/buffers/isArrayBuffer.ts | 3 - src/util/buffers/isFloat32.ts | 6 - src/util/buffers/isUint8Array.ts | 4 - src/util/buffers/printOctets.ts | 14 - src/util/buffers/strings.ts | 16 - src/util/buffers/toBuf.ts | 8 - src/util/buffers/toDataUri.ts | 7 - src/util/buffers/toUint8Array.ts | 10 - src/util/buffers/types.ts | 126 ---- src/util/buffers/utf8/CachedUtf8Decoder.ts | 54 -- .../buffers/utf8/__tests__/encode.spec.ts | 23 - .../buffers/utf8/__tests__/isUtf8.spec.ts | 54 -- src/util/buffers/utf8/decodeAscii.ts | 167 ----- src/util/buffers/utf8/decodeUtf8/README.md | 96 --- .../decodeUtf8/__tests__/decodeUtf8.spec.ts | 120 --- src/util/buffers/utf8/decodeUtf8/index.ts | 3 - src/util/buffers/utf8/decodeUtf8/v1.ts | 38 - src/util/buffers/utf8/decodeUtf8/v10.ts | 39 - src/util/buffers/utf8/decodeUtf8/v11.ts | 2 - src/util/buffers/utf8/decodeUtf8/v12.ts | 5 - src/util/buffers/utf8/decodeUtf8/v13.ts | 27 - src/util/buffers/utf8/decodeUtf8/v14.ts | 8 - src/util/buffers/utf8/decodeUtf8/v15.ts | 16 - src/util/buffers/utf8/decodeUtf8/v16.ts | 29 - src/util/buffers/utf8/decodeUtf8/v17.ts | 37 - src/util/buffers/utf8/decodeUtf8/v18.ts | 36 - src/util/buffers/utf8/decodeUtf8/v19.ts | 3 - src/util/buffers/utf8/decodeUtf8/v2.ts | 2 - src/util/buffers/utf8/decodeUtf8/v3.ts | 4 - src/util/buffers/utf8/decodeUtf8/v4.ts | 4 - src/util/buffers/utf8/decodeUtf8/v5.ts | 30 - src/util/buffers/utf8/decodeUtf8/v6.ts | 6 - src/util/buffers/utf8/decodeUtf8/v7.ts | 32 - src/util/buffers/utf8/decodeUtf8/v8.ts | 39 - src/util/buffers/utf8/decodeUtf8/v9.ts | 35 - src/util/buffers/utf8/encode.ts | 58 -- src/util/buffers/utf8/isUtf8.ts | 45 -- .../buffers/utf8/sharedCachedUtf8Decoder.ts | 3 - src/util/codegen/Codegen.ts | 296 -------- src/util/codegen/README.md | 17 - src/util/codegen/__tests__/Codegen.spec.ts | 31 - src/util/codegen/compile.ts | 7 - src/util/codegen/dynamicFunction.ts | 16 - src/util/codegen/index.ts | 4 +- src/util/codegen/switch.ts | 15 - src/util/codegen/types.ts | 38 - src/util/codegen/util/JsExpression.ts | 41 -- src/util/codegen/util/helpers.ts | 6 - src/util/codegen/util/normalizeAccessor.ts | 7 - src/util/router/codegen.ts | 4 +- src/util/router/router.ts | 2 +- src/util/router/tree.ts | 2 +- src/util/sort/insertion.ts | 22 +- src/util/sort/insertion2.ts | 23 +- src/util/strings/__tests__/asString.spec.ts | 33 - src/util/strings/__tests__/utf8.spec.ts | 26 - src/util/strings/__tests__/util.spec.ts | 54 -- src/util/strings/__tests__/wordWrap.spec.ts | 42 -- src/util/strings/asString.ts | 22 - src/util/strings/escape.ts | 134 ---- src/util/strings/flatstr.ts | 5 - src/util/strings/utf8.ts | 27 - src/util/strings/util.ts | 8 - src/util/strings/wordWrap.ts | 21 - src/web3/adl/hamt-crdt/Hamt.ts | 2 +- src/web3/adl/hamt-crdt/HamtFrame.ts | 2 +- src/web3/adl/hamt-crdt/__tests__/Hamt.spec.ts | 2 +- src/web3/codec/codecs/cbor.ts | 4 +- src/web3/codec/codecs/writer.ts | 2 +- src/web3/codec/types.ts | 2 +- src/web3/multiformats/Multihash.ts | 2 +- tsconfig.json | 1 - yarn.lock | 14 + 436 files changed, 299 insertions(+), 21718 deletions(-) delete mode 100644 src/json-binary/README.md delete mode 100644 src/json-binary/__tests__/automated.spec.ts delete mode 100644 src/json-binary/__tests__/stringify.spec.ts delete mode 100644 src/json-binary/codec.ts delete mode 100644 src/json-binary/constants.ts delete mode 100644 src/json-binary/types.ts delete mode 100644 src/json-brand/README.md delete mode 100644 src/json-brand/global.d.ts delete mode 100644 src/json-brand/index.d.ts delete mode 100644 src/json-brand/types.ts delete mode 100644 src/json-pack/JsonPackExtension.ts delete mode 100644 src/json-pack/JsonPackValue.ts delete mode 100644 src/json-pack/README.md delete mode 100644 src/json-pack/__bench__/bench.bson.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.cbor-dag.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.cbor.decoding.ts delete mode 100644 src/json-pack/__bench__/bench.cbor.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.encoders.ts delete mode 100644 src/json-pack/__bench__/bench.encoding.cbor.ts delete mode 100644 src/json-pack/__bench__/bench.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.ion.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.json.decoding.ts delete mode 100644 src/json-pack/__bench__/bench.json.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.msgpack.decoding.ts delete mode 100644 src/json-pack/__bench__/bench.msgpack.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.resp.decoding.ts delete mode 100644 src/json-pack/__bench__/bench.resp.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.shallow-read.ts delete mode 100644 src/json-pack/__bench__/bench.slice.ts delete mode 100644 src/json-pack/__bench__/bench.ubjson.decoding.ts delete mode 100644 src/json-pack/__bench__/bench.ubjson.encoding.ts delete mode 100644 src/json-pack/__bench__/bench.writer-size.ts delete mode 100644 src/json-pack/__bench__/profiler/cbor-decoding.ts delete mode 100644 src/json-pack/__bench__/profiler/slices.ts delete mode 100644 src/json-pack/__bench__/profiler/time.ts delete mode 100644 src/json-pack/__bench__/profiler/truncate.ts delete mode 100644 src/json-pack/__demos__/cbor.ts delete mode 100644 src/json-pack/__demos__/json.ts delete mode 100644 src/json-pack/__demos__/msgpack.ts delete mode 100644 src/json-pack/__demos__/ubjson.ts delete mode 100644 src/json-pack/bencode/BencodeDecoder.ts delete mode 100644 src/json-pack/bencode/BencodeEncoder.ts delete mode 100644 src/json-pack/bencode/README.md delete mode 100644 src/json-pack/bencode/__tests__/BencodeDecoder.spec.ts delete mode 100644 src/json-pack/bencode/__tests__/BencodeEncoder.spec.ts delete mode 100644 src/json-pack/bencode/__tests__/automated.spec.ts delete mode 100644 src/json-pack/bencode/types.ts delete mode 100644 src/json-pack/bson/BsonEncoder.ts delete mode 100644 src/json-pack/bson/README.md delete mode 100644 src/json-pack/bson/__tests__/BsonEncoder-values.spec.ts delete mode 100644 src/json-pack/bson/__tests__/BsonEncoder.spec.ts delete mode 100644 src/json-pack/bson/__tests__/codec.spec.ts delete mode 100644 src/json-pack/bson/index.ts delete mode 100644 src/json-pack/bson/values.ts delete mode 100644 src/json-pack/cbor/CborDecoder.ts delete mode 100644 src/json-pack/cbor/CborDecoderBase.ts delete mode 100644 src/json-pack/cbor/CborDecoderDag.ts delete mode 100644 src/json-pack/cbor/CborEncoder.ts delete mode 100644 src/json-pack/cbor/CborEncoderDag.ts delete mode 100644 src/json-pack/cbor/CborEncoderFast.ts delete mode 100644 src/json-pack/cbor/CborEncoderStable.ts delete mode 100644 src/json-pack/cbor/README.md delete mode 100644 src/json-pack/cbor/__tests__/CborDecoder.readLevel.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborDecoder.shallow-reading.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborDecoder.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborDecoder.validate.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborDecoderDag.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborEncoder.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborEncoderDag.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/CborEncoderStable.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/cbor-js-testcases.ts delete mode 100644 src/json-pack/cbor/__tests__/cbor-js.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/codec.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/fuzzing.spec.ts delete mode 100644 src/json-pack/cbor/__tests__/shallow-read.genShallowRead.spec.ts delete mode 100644 src/json-pack/cbor/constants.ts delete mode 100644 src/json-pack/cbor/shared.ts delete mode 100644 src/json-pack/cbor/types.ts delete mode 100644 src/json-pack/codecs/Codecs.ts delete mode 100644 src/json-pack/codecs/cbor.ts delete mode 100644 src/json-pack/codecs/json.ts delete mode 100644 src/json-pack/codecs/msgpack.ts delete mode 100644 src/json-pack/codecs/types.ts delete mode 100644 src/json-pack/constants.ts delete mode 100644 src/json-pack/ion/Import.ts delete mode 100644 src/json-pack/ion/IonEncoderFast.ts delete mode 100644 src/json-pack/ion/README.md delete mode 100644 src/json-pack/ion/__tests__/Import.spec.ts delete mode 100644 src/json-pack/ion/__tests__/IonEncoder.spec.ts delete mode 100644 src/json-pack/ion/__tests__/automated.spec.ts delete mode 100644 src/json-pack/ion/ast.ts delete mode 100644 src/json-pack/ion/constants.ts delete mode 100644 src/json-pack/ion/symbols.ts delete mode 100644 src/json-pack/ion/types.ts delete mode 100644 src/json-pack/json/JsonDecoder.ts delete mode 100644 src/json-pack/json/JsonDecoderDag.ts delete mode 100644 src/json-pack/json/JsonEncoder.ts delete mode 100644 src/json-pack/json/JsonEncoderDag.ts delete mode 100644 src/json-pack/json/JsonEncoderStable.ts delete mode 100644 src/json-pack/json/README.md delete mode 100644 src/json-pack/json/__tests__/JsonDecoder.spec.ts delete mode 100644 src/json-pack/json/__tests__/JsonDecoderDag.spec.ts delete mode 100644 src/json-pack/json/__tests__/JsonEncoder.spec.ts delete mode 100644 src/json-pack/json/__tests__/JsonEncoderDag.spec.ts delete mode 100644 src/json-pack/json/__tests__/automated.spec.ts delete mode 100644 src/json-pack/json/__tests__/fuzzer.spec.ts delete mode 100644 src/json-pack/json/__tests__/memory-leaks.spec.ts delete mode 100644 src/json-pack/json/types.ts delete mode 100644 src/json-pack/json/util.ts delete mode 100644 src/json-pack/msgpack/MsgPackDecoder.ts delete mode 100644 src/json-pack/msgpack/MsgPackDecoderFast.ts delete mode 100644 src/json-pack/msgpack/MsgPackEncoder.ts delete mode 100644 src/json-pack/msgpack/MsgPackEncoderFast.ts delete mode 100644 src/json-pack/msgpack/MsgPackEncoderStable.ts delete mode 100644 src/json-pack/msgpack/MsgPackToJsonConverter.ts delete mode 100644 src/json-pack/msgpack/README.md delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackDecoder.one-level.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackDecoder.shallow-reading.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackDecoder.validate.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackDecoderFast.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackEncoder.codec.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackEncoder.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackEncoderFast.overwrite.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackEncoderFast.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackEncoderStable.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/MsgPackToJsonConverter.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/codec.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/decode.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/fuzzing.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/numbers.spec.ts delete mode 100644 src/json-pack/msgpack/__tests__/shallow-read.genShallowRead.spec.ts delete mode 100644 src/json-pack/msgpack/constants.ts delete mode 100644 src/json-pack/msgpack/index.ts delete mode 100644 src/json-pack/msgpack/shallow-read.ts delete mode 100644 src/json-pack/msgpack/types.ts delete mode 100644 src/json-pack/msgpack/util.ts delete mode 100644 src/json-pack/resp/README.md delete mode 100644 src/json-pack/resp/RespDecoder.ts delete mode 100644 src/json-pack/resp/RespEncoder.ts delete mode 100644 src/json-pack/resp/RespEncoderLegacy.ts delete mode 100644 src/json-pack/resp/RespStreamingDecoder.ts delete mode 100644 src/json-pack/resp/__tests__/RespDecoder.spec.ts delete mode 100644 src/json-pack/resp/__tests__/RespEncoder.spec.ts delete mode 100644 src/json-pack/resp/__tests__/RespEncoderLegacy.spec.ts delete mode 100644 src/json-pack/resp/__tests__/RespStreamingDecoder.spec.ts delete mode 100644 src/json-pack/resp/__tests__/codec.spec.ts delete mode 100644 src/json-pack/resp/__tests__/fuzzing.spec.ts delete mode 100644 src/json-pack/resp/__tests__/skipping.spec.ts delete mode 100644 src/json-pack/resp/constants.ts delete mode 100644 src/json-pack/resp/extensions.ts delete mode 100644 src/json-pack/resp/index.ts delete mode 100644 src/json-pack/types.ts delete mode 100644 src/json-pack/ubjson/README.md delete mode 100644 src/json-pack/ubjson/UbjsonDecoder.ts delete mode 100644 src/json-pack/ubjson/UbjsonEncoder.ts delete mode 100644 src/json-pack/ubjson/__tests__/UbjsonDecoder.spec.ts delete mode 100644 src/json-pack/ubjson/__tests__/UbjsonEncoder.spec.ts delete mode 100644 src/json-pack/ubjson/__tests__/automated.spec.ts delete mode 100644 src/json-pack/ubjson/__tests__/fuzzer.spec.ts delete mode 100644 src/json-pack/util/CompressionTable.ts delete mode 100644 src/json-pack/util/DecompressionTable.ts delete mode 100644 src/json-pack/util/__tests__/CompressionTable.spec.ts delete mode 100644 src/json-pack/util/__tests__/DecompressionTable.spec.ts delete mode 100644 src/json-pack/util/objKeyCmp.ts delete mode 100644 src/util/base64/README.md delete mode 100644 src/util/base64/__bench__/decode.js delete mode 100644 src/util/base64/__bench__/encode.js delete mode 100644 src/util/base64/__tests__/decode-base64url.spec.ts delete mode 100644 src/util/base64/__tests__/decode-bin.spec.ts delete mode 100644 src/util/base64/__tests__/decode.spec.ts delete mode 100644 src/util/base64/__tests__/encode-base64url.spec.ts delete mode 100644 src/util/base64/__tests__/encode-bin.spec.ts delete mode 100644 src/util/base64/__tests__/encode.spec.ts delete mode 100644 src/util/base64/constants.ts delete mode 100644 src/util/base64/createFromBase64.ts delete mode 100644 src/util/base64/createFromBase64Bin.ts delete mode 100644 src/util/base64/createToBase64.ts delete mode 100644 src/util/base64/createToBase64Bin.ts delete mode 100644 src/util/base64/createToBase64BinUint8.ts delete mode 100644 src/util/base64/fromBase64.ts delete mode 100644 src/util/base64/fromBase64Bin.ts delete mode 100644 src/util/base64/fromBase64Url.ts delete mode 100644 src/util/base64/index.ts delete mode 100644 src/util/base64/toBase64.ts delete mode 100644 src/util/base64/toBase64Bin.ts delete mode 100644 src/util/base64/toBase64Url.ts delete mode 100644 src/util/buffers/Reader.ts delete mode 100644 src/util/buffers/Slice.ts delete mode 100644 src/util/buffers/StreamingOctetReader.ts delete mode 100644 src/util/buffers/StreamingReader.ts delete mode 100644 src/util/buffers/Uint8ArrayCut.ts delete mode 100644 src/util/buffers/Writer.ts delete mode 100644 src/util/buffers/__bench__/bench.decodeUtf8.ts delete mode 100644 src/util/buffers/__tests__/StreamingReader.spec.ts delete mode 100644 src/util/buffers/__tests__/isFloat32.spec.ts delete mode 100644 src/util/buffers/b.ts delete mode 100644 src/util/buffers/bufferToUint8Array.ts delete mode 100644 src/util/buffers/cmpUint8Array.ts delete mode 100644 src/util/buffers/cmpUint8Array2.ts delete mode 100644 src/util/buffers/cmpUint8Array3.ts delete mode 100644 src/util/buffers/concat.ts delete mode 100644 src/util/buffers/copy.ts delete mode 100644 src/util/buffers/f16.ts delete mode 100644 src/util/buffers/isArrayBuffer.ts delete mode 100644 src/util/buffers/isFloat32.ts delete mode 100644 src/util/buffers/isUint8Array.ts delete mode 100644 src/util/buffers/printOctets.ts delete mode 100644 src/util/buffers/strings.ts delete mode 100644 src/util/buffers/toBuf.ts delete mode 100644 src/util/buffers/toDataUri.ts delete mode 100644 src/util/buffers/toUint8Array.ts delete mode 100644 src/util/buffers/types.ts delete mode 100644 src/util/buffers/utf8/CachedUtf8Decoder.ts delete mode 100644 src/util/buffers/utf8/__tests__/encode.spec.ts delete mode 100644 src/util/buffers/utf8/__tests__/isUtf8.spec.ts delete mode 100644 src/util/buffers/utf8/decodeAscii.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/README.md delete mode 100644 src/util/buffers/utf8/decodeUtf8/__tests__/decodeUtf8.spec.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/index.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v1.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v10.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v11.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v12.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v13.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v14.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v15.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v16.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v17.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v18.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v19.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v2.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v3.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v4.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v5.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v6.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v7.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v8.ts delete mode 100644 src/util/buffers/utf8/decodeUtf8/v9.ts delete mode 100644 src/util/buffers/utf8/encode.ts delete mode 100644 src/util/buffers/utf8/isUtf8.ts delete mode 100644 src/util/buffers/utf8/sharedCachedUtf8Decoder.ts delete mode 100644 src/util/codegen/Codegen.ts delete mode 100644 src/util/codegen/README.md delete mode 100644 src/util/codegen/__tests__/Codegen.spec.ts delete mode 100644 src/util/codegen/compile.ts delete mode 100644 src/util/codegen/dynamicFunction.ts delete mode 100644 src/util/codegen/switch.ts delete mode 100644 src/util/codegen/types.ts delete mode 100644 src/util/codegen/util/JsExpression.ts delete mode 100644 src/util/codegen/util/helpers.ts delete mode 100644 src/util/codegen/util/normalizeAccessor.ts delete mode 100644 src/util/strings/__tests__/asString.spec.ts delete mode 100644 src/util/strings/__tests__/utf8.spec.ts delete mode 100644 src/util/strings/__tests__/util.spec.ts delete mode 100644 src/util/strings/__tests__/wordWrap.spec.ts delete mode 100644 src/util/strings/asString.ts delete mode 100644 src/util/strings/escape.ts delete mode 100644 src/util/strings/flatstr.ts delete mode 100644 src/util/strings/utf8.ts delete mode 100644 src/util/strings/util.ts delete mode 100644 src/util/strings/wordWrap.ts diff --git a/package.json b/package.json index 48f37e25bf..ef4d58c1df 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,8 @@ } }, "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/json-pack": "^1.0.1", "arg": "^5.0.2", "hyperdyperid": "^1.2.0", "multibase": "^4.0.6", diff --git a/src/index.ts b/src/index.ts index c09f80ac22..ccefde3bc6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,13 +6,12 @@ * ``` */ -export type * from './json-binary/types'; -export type * from './json-brand/types'; +export type * from '@jsonjoy.com/json-pack/lib/json-binary/types'; +export type * from '@jsonjoy.com/json-pack/lib/json-brand/types'; export type * from './json-crdt'; export type * from './json-crdt-patch'; export type * from './json-crdt-extensions'; export type * from './json-expression/types'; -export type * from './json-pack/types'; export type * from './json-patch/types'; export type * from './json-pointer/types'; export type * from './json-schema/types'; diff --git a/src/json-binary/README.md b/src/json-binary/README.md deleted file mode 100644 index edba4b14fc..0000000000 --- a/src/json-binary/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# json-binary - -A JSON serializer and parser which supports `Uint8Array` binary data. -Encodes binary data as Base64 encoded data URI strings. - -```ts -import * as JSONB from 'json-joy/lib/json-binary'; - -const data = { - foo: new Uint8Array([1, 2, 3]), -}; - -const json = JSONB.stringify(data); -// {"foo":"data:application/octet-stream;base64,AAECAw=="} - -const data2 = JSONB.parse(json); -// { foo: Uint8Array { 1, 2, 3 } } -``` diff --git a/src/json-binary/__tests__/automated.spec.ts b/src/json-binary/__tests__/automated.spec.ts deleted file mode 100644 index bd8f0a4e29..0000000000 --- a/src/json-binary/__tests__/automated.spec.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {stringify, parse} from '..'; -import {documents} from '../../__tests__/json-documents'; -import {binaryDocuments} from '../../__tests__/binary-documents'; -import {msgPackDocuments} from '../../__tests__/msgpack-documents'; - -for (const document of [...documents, ...binaryDocuments, ...msgPackDocuments]) { - (document.only ? test.only : test)(document.name, () => { - const encoded = stringify(document.json); - const decoded = parse(encoded); - expect(decoded).toStrictEqual(document.json); - }); -} diff --git a/src/json-binary/__tests__/stringify.spec.ts b/src/json-binary/__tests__/stringify.spec.ts deleted file mode 100644 index f304981214..0000000000 --- a/src/json-binary/__tests__/stringify.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {stringify} from '..'; -import {binUriStart} from '../constants'; - -test('can stringify an empty buffer', () => { - const json = stringify(new Uint8Array(0)); - expect(json).toBe(`"${binUriStart}"`); -}); - -test('can stringify a short buffer', () => { - const json = stringify(new Uint8Array([0, 1, 2, 3])); - expect(json).toBe(`"${binUriStart}AAECAw=="`); -}); - -test('can stringify a short buffer in an object', () => { - const json = stringify({ - foo: new Uint8Array([0, 1, 2, 3]), - }); - expect(json).toBe(`{"foo":"${binUriStart}AAECAw=="}`); -}); - -test('can stringify a short buffer in an array', () => { - const json = stringify([null, 1, new Uint8Array([0, 1, 2, 3]), 'a']); - expect(json).toBe(`[null,1,"${binUriStart}AAECAw==","a"]`); -}); diff --git a/src/json-binary/codec.ts b/src/json-binary/codec.ts deleted file mode 100644 index 87df43276d..0000000000 --- a/src/json-binary/codec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import {JsonPackExtension, JsonPackValue} from '../json-pack/msgpack'; -import {fromBase64, toBase64} from '../util/base64'; -import {isUint8Array} from '../util/buffers/isUint8Array'; -import {binUriStart, msgPackExtStart, msgPackUriStart} from './constants'; -import {binary_string} from './types'; - -const binUriStartLength = binUriStart.length; -const msgPackUriStartLength = msgPackUriStart.length; -const msgPackExtStartLength = msgPackExtStart.length; -const minDataUri = Math.min(binUriStartLength, msgPackUriStartLength); - -const parseExtDataUri = (uri: string): JsonPackExtension => { - uri = uri.substring(msgPackExtStartLength); - const commaIndex = uri.indexOf(','); - if (commaIndex === -1) throw new Error('INVALID_EXT_DATA_URI'); - const typeString = uri.substring(0, commaIndex); - const buf = fromBase64(uri.substring(commaIndex + 1)); - return new JsonPackExtension(Number(typeString), buf); -}; - -/** - * Replaces strings with Uint8Arrays in-place. - */ -export const unwrapBinary = (value: unknown): unknown => { - if (!value) return value; - if (value instanceof Array) { - const len = value.length; - for (let i = 0; i < len; i++) { - const item = value[i]; - switch (typeof item) { - case 'object': { - unwrapBinary(item); - continue; - } - case 'string': { - if (item.length < minDataUri) continue; - if (item.substring(0, binUriStartLength) === binUriStart) - value[i] = fromBase64(item.substring(binUriStartLength)); - else if (item.substring(0, msgPackUriStartLength) === msgPackUriStart) - value[i] = new JsonPackValue(fromBase64(item.substring(msgPackUriStartLength))); - else if (item.substring(0, msgPackExtStartLength) === msgPackExtStart) value[i] = parseExtDataUri(item); - } - } - } - return value; - } - if (typeof value === 'object') { - for (const key in value) { - const item = (value as any)[key]; - switch (typeof item) { - case 'object': { - unwrapBinary(item); - continue; - } - case 'string': { - if (item.length < minDataUri) continue; - if (item.substring(0, binUriStartLength) === binUriStart) { - const buf = fromBase64(item.substring(binUriStartLength)); - (value as any)[key] = buf; - } else if (item.substring(0, msgPackUriStartLength) === msgPackUriStart) { - (value as any)[key] = new JsonPackValue(fromBase64(item.substring(msgPackUriStartLength))); - } else if (item.substring(0, msgPackExtStartLength) === msgPackExtStart) - (value as any)[key] = parseExtDataUri(item); - } - } - } - return value; - } - if (typeof value === 'string') { - if (value.length < minDataUri) return value; - if (value.substring(0, binUriStartLength) === binUriStart) return fromBase64(value.substring(binUriStartLength)); - if (value.substring(0, msgPackUriStartLength) === msgPackUriStart) - return new JsonPackValue(fromBase64(value.substring(msgPackUriStartLength))); - if (value.substring(0, msgPackExtStartLength) === msgPackExtStart) return parseExtDataUri(value); - else return value; - } - return value; -}; - -export const parse = (json: string): unknown => { - const parsed = JSON.parse(json); - return unwrapBinary(parsed); -}; - -export const stringifyBinary = (value: T): binary_string => - >(binUriStart + toBase64(value)); - -/** - * Replaces Uint8Arrays with strings, returns a new structure, - * without mutating the original. - */ -export const wrapBinary = (value: unknown): unknown => { - if (!value) return value; - if (isUint8Array(value)) return stringifyBinary(value); - if (value instanceof Array) { - const out: unknown[] = []; - const len = value.length; - for (let i = 0; i < len; i++) { - const item = value[i]; - out.push(!item || typeof item !== 'object' ? item : wrapBinary(item)); - } - return out; - } - if (value instanceof JsonPackValue) return msgPackUriStart + toBase64(value.val); - if (value instanceof JsonPackExtension) return msgPackExtStart + value.tag + ',' + toBase64(value.val); - if (typeof value === 'object') { - const out: {[key: string]: unknown} = {}; - for (const key in value) { - const item = (value as any)[key]; - out[key] = !item || typeof item !== 'object' ? item : wrapBinary(item); - } - return out; - } - return value; -}; - -type Stringify = - | ((value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number) => string) - | ((value: any, replacer?: (number | string)[] | null, space?: string | number) => string); - -export const stringify: Stringify = (value: unknown, replacer: any, space: any) => { - const wrapped = wrapBinary(value); - return JSON.stringify(wrapped, replacer, space); -}; diff --git a/src/json-binary/constants.ts b/src/json-binary/constants.ts deleted file mode 100644 index e5afe7a993..0000000000 --- a/src/json-binary/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const binUriStart = 'data:application/octet-stream;base64,'; -const msgPackUriHeader = 'data:application/msgpack;base64'; -export const msgPackUriStart = msgPackUriHeader + ','; -export const msgPackExtStart = msgPackUriHeader + ';ext='; diff --git a/src/json-binary/index.ts b/src/json-binary/index.ts index f36840daa2..4b173b2b67 100644 --- a/src/json-binary/index.ts +++ b/src/json-binary/index.ts @@ -1,3 +1 @@ -export * from './types'; -export * from './constants'; -export * from './codec'; +export * from '@jsonjoy.com/json-pack/lib/json-binary'; diff --git a/src/json-binary/types.ts b/src/json-binary/types.ts deleted file mode 100644 index 63877c7194..0000000000 --- a/src/json-binary/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type {MsgPack} from '../json-pack/msgpack'; -import type {CborUint8Array} from '../json-pack/cbor/types'; -import type {Brand} from '../util/types'; - -export type base64_string = Brand; -export type binary_string = Brand< - `data:application/octet-stream;base64,${base64_string}`, - T, - 'binary_string' ->; -export type cbor_string = Brand< - `data:application/cbor;base64,${base64_string>}`, - T, - 'cbor_string' ->; -export type msgpack_string = Brand< - `data:application/msgpack;base64,${base64_string>}`, - T, - 'msgpack_string' ->; diff --git a/src/json-brand/README.md b/src/json-brand/README.md deleted file mode 100644 index 1a99005394..0000000000 --- a/src/json-brand/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# json-brand - -TypeScript branded type for a JSON string. - -```ts -import {JSON, json} from 'json-joy/lib/json-brand'; - -const str = '{"hello": "world"}' as json<{hello: string}>; - -JSON.parse(str).hello; // OK -JSON.parse(str).foo; // Error: ... -``` diff --git a/src/json-brand/global.d.ts b/src/json-brand/global.d.ts deleted file mode 100644 index b9a6ec2575..0000000000 --- a/src/json-brand/global.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare global { - interface JSON { - parse(text: json, reviver?: (key: any, value: any) => any): T; - stringify(value: T, replacer?: (key: string, value: any) => any, space?: string | number): json; - stringify(value: T, replacer?: (number | string)[] | null, space?: string | number): json; - } -} diff --git a/src/json-brand/index.d.ts b/src/json-brand/index.d.ts deleted file mode 100644 index a6c51e2666..0000000000 --- a/src/json-brand/index.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type json = string & {__JSON__: T}; -export type json_string = json; - -export interface JSON { - parse(text: json, reviver?: (key: any, value: any) => any): T; - stringify(value: T, replacer?: (key: string, value: any) => any, space?: string | number): json; - stringify(value: T, replacer?: (number | string)[] | null, space?: string | number): json; -} - -export const JSON: JSON; diff --git a/src/json-brand/index.ts b/src/json-brand/index.ts index 2a85af098e..58890235f8 100644 --- a/src/json-brand/index.ts +++ b/src/json-brand/index.ts @@ -1,5 +1 @@ -import * as type from './types'; - -export const JSON = (typeof global !== 'undefined' ? global.JSON : window.JSON) as unknown as type.JSON; - -export type {json, json_string} from './types'; +export * from '@jsonjoy.com/json-pack/lib/json-brand'; diff --git a/src/json-brand/types.ts b/src/json-brand/types.ts deleted file mode 100644 index b3735b1ce4..0000000000 --- a/src/json-brand/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type json = json_string; - -export type json_string = string & {__BRAND__: 'JSON_STRING'; __TYPE__: T}; - -export interface JSON { - parse(text: json, reviver?: (key: any, value: any) => any): T; - stringify(value: T, replacer?: (key: string, value: any) => any, space?: string | number): json; - stringify(value: T, replacer?: (number | string)[] | null, space?: string | number): json; -} diff --git a/src/json-cli/json-pack.ts b/src/json-cli/json-pack.ts index d7ca1982e0..5283d112a4 100644 --- a/src/json-cli/json-pack.ts +++ b/src/json-cli/json-pack.ts @@ -1,7 +1,7 @@ import {readFileSync} from 'fs'; -import {MsgPackEncoder} from '../json-pack/msgpack'; -import {CborEncoder} from '../json-pack/cbor/CborEncoder'; -import * as JSONB from '../json-binary'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import * as JSONB from '@jsonjoy.com/json-pack/lib/json-binary'; import arg from 'arg'; const args = arg( diff --git a/src/json-cli/json-unpack.ts b/src/json-cli/json-unpack.ts index 1f493231c6..5cba8c0159 100644 --- a/src/json-cli/json-unpack.ts +++ b/src/json-cli/json-unpack.ts @@ -1,6 +1,6 @@ import {readFileSync} from 'fs'; -import {MsgPackDecoderFast} from '../json-pack/msgpack'; -import {CborDecoder} from '../json-pack/cbor/CborDecoder'; +import {MsgPackDecoderFast} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import * as JSONB from '../json-binary'; import arg from 'arg'; diff --git a/src/json-clone/cloneBinary.ts b/src/json-clone/cloneBinary.ts index 533f60a837..fc5b110ebd 100644 --- a/src/json-clone/cloneBinary.ts +++ b/src/json-clone/cloneBinary.ts @@ -1,4 +1,4 @@ -import {isUint8Array} from '../util/buffers/isUint8Array'; +import {isUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/isUint8Array'; const {isArray} = Array; const objectKeys = Object.keys; diff --git a/src/json-crdt-patch/PatchBuilder.ts b/src/json-crdt-patch/PatchBuilder.ts index 6da120f103..2116af5d00 100644 --- a/src/json-crdt-patch/PatchBuilder.ts +++ b/src/json-crdt-patch/PatchBuilder.ts @@ -16,7 +16,7 @@ import { NopOp, } from './operations'; import {IClock, ITimestampStruct, ITimespanStruct, ts, Timestamp} from './clock'; -import {isUint8Array} from '../util/buffers/isUint8Array'; +import {isUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/isUint8Array'; import {Patch} from './Patch'; import {ORIGIN} from './constants'; import {VectorDelayedValue} from './builder/Tuple'; diff --git a/src/json-crdt-patch/__demos__/PatchBuilder-operations.ts b/src/json-crdt-patch/__demos__/PatchBuilder-operations.ts index 9784ab6c1b..5e06bd8524 100644 --- a/src/json-crdt-patch/__demos__/PatchBuilder-operations.ts +++ b/src/json-crdt-patch/__demos__/PatchBuilder-operations.ts @@ -11,7 +11,7 @@ import {LogicalClock} from '../clock'; import * as verbose from '../codec/verbose'; import * as compact from '../codec/compact'; import * as binary from '../codec/binary'; -import * as cbor from '../../json-pack/cbor/shared'; +import * as cbor from '@jsonjoy.com/json-pack/lib/cbor/shared'; const clock = new LogicalClock(123, 456); const builder = new PatchBuilder(clock); diff --git a/src/json-crdt-patch/codec/binary/Decoder.ts b/src/json-crdt-patch/codec/binary/Decoder.ts index 7382fe65f2..e45b892e0b 100644 --- a/src/json-crdt-patch/codec/binary/Decoder.ts +++ b/src/json-crdt-patch/codec/binary/Decoder.ts @@ -3,7 +3,7 @@ import {interval, ITimespanStruct, ITimestampStruct, ClockVector, ServerClockVec import {Patch} from '../../Patch'; import {PatchBuilder} from '../../PatchBuilder'; import {SESSION} from '../../constants'; -import {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {JsonCrdtPatchOpcode} from '../../constants'; /** diff --git a/src/json-crdt-patch/codec/binary/Encoder.ts b/src/json-crdt-patch/codec/binary/Encoder.ts index 72106ddf23..f808f1b5a2 100644 --- a/src/json-crdt-patch/codec/binary/Encoder.ts +++ b/src/json-crdt-patch/codec/binary/Encoder.ts @@ -2,7 +2,7 @@ import * as operations from '../../operations'; import {JsonCrdtPatchOpcodeOverlay} from '../../constants'; import {CrdtWriter} from '../../util/binary/CrdtWriter'; import {ITimespanStruct, ITimestampStruct, Timestamp} from '../../clock'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import type {JsonCrdtPatchOperation, Patch} from '../../Patch'; /** diff --git a/src/json-crdt-patch/codec/compact-binary/decode.ts b/src/json-crdt-patch/codec/compact-binary/decode.ts index 547f66f3b9..a941ac4717 100644 --- a/src/json-crdt-patch/codec/compact-binary/decode.ts +++ b/src/json-crdt-patch/codec/compact-binary/decode.ts @@ -1,5 +1,5 @@ +import {decode as decodeJson, type CborUint8Array} from '@jsonjoy.com/json-pack/lib/cbor/shared'; import {decode as decodeCompact} from '../compact/decode'; -import {decode as decodeJson, type CborUint8Array} from '../../../json-pack/cbor/shared'; import type {Patch} from '../../Patch'; import type {CompactCodecPatch} from '../compact/types'; diff --git a/src/json-crdt-patch/codec/compact-binary/encode.ts b/src/json-crdt-patch/codec/compact-binary/encode.ts index 8c15e03fe6..cd7c072e9c 100644 --- a/src/json-crdt-patch/codec/compact-binary/encode.ts +++ b/src/json-crdt-patch/codec/compact-binary/encode.ts @@ -1,5 +1,5 @@ +import {encode as encodeJson, type CborUint8Array} from '@jsonjoy.com/json-pack/lib/cbor/shared'; import {encode as encodeCompact} from '../compact/encode'; -import {encode as encodeJson, type CborUint8Array} from '../../../json-pack/cbor/shared'; import type {Patch} from '../../Patch'; import type {CompactCodecPatch} from '../compact/types'; diff --git a/src/json-crdt-patch/codec/compact/decode.ts b/src/json-crdt-patch/codec/compact/decode.ts index 7c55674822..549622a08b 100644 --- a/src/json-crdt-patch/codec/compact/decode.ts +++ b/src/json-crdt-patch/codec/compact/decode.ts @@ -1,5 +1,5 @@ import {JsonCrdtPatchOpcode} from '../../constants'; -import {fromBase64} from '../../../util/base64/fromBase64'; +import {fromBase64} from '@jsonjoy.com/base64/lib/fromBase64'; import {ITimespanStruct, ITimestampStruct, ClockVector, ServerClockVector, Timespan, Timestamp} from '../../clock'; import {Patch} from '../../Patch'; import {PatchBuilder} from '../../PatchBuilder'; diff --git a/src/json-crdt-patch/codec/compact/encode.ts b/src/json-crdt-patch/codec/compact/encode.ts index 03486f6c40..2e9fee7409 100644 --- a/src/json-crdt-patch/codec/compact/encode.ts +++ b/src/json-crdt-patch/codec/compact/encode.ts @@ -2,7 +2,7 @@ import * as operations from '../../operations'; import {ITimespanStruct, ITimestampStruct, Timestamp} from '../../clock'; import {Patch} from '../../Patch'; import {JsonCrdtPatchOpcode, SESSION} from '../../constants'; -import {toBase64} from '../../../util/base64/toBase64'; +import {toBase64} from '@jsonjoy.com/base64/lib/toBase64'; import type * as types from './types'; const timestamp = (sid: number, ts: ITimestampStruct): types.CompactCodecTimestamp => { diff --git a/src/json-crdt-patch/codec/verbose/decode.ts b/src/json-crdt-patch/codec/verbose/decode.ts index 1d37d3d3a7..8d8d580b48 100644 --- a/src/json-crdt-patch/codec/verbose/decode.ts +++ b/src/json-crdt-patch/codec/verbose/decode.ts @@ -1,4 +1,4 @@ -import {fromBase64} from '../../../util/base64/fromBase64'; +import {fromBase64} from '@jsonjoy.com/base64/lib/fromBase64'; import {ts, ClockVector, ServerClockVector, tss, ITimestampStruct} from '../../clock'; import {SESSION} from '../../constants'; import {Patch} from '../../Patch'; diff --git a/src/json-crdt-patch/codec/verbose/encode.ts b/src/json-crdt-patch/codec/verbose/encode.ts index e169b813c8..877b3bff09 100644 --- a/src/json-crdt-patch/codec/verbose/encode.ts +++ b/src/json-crdt-patch/codec/verbose/encode.ts @@ -1,7 +1,7 @@ import * as operations from '../../operations'; import {Patch} from '../../Patch'; import {SESSION} from '../../constants'; -import {toBase64} from '../../../util/base64/toBase64'; +import {toBase64} from '@jsonjoy.com/base64/lib/toBase64'; import {ITimestampStruct, Timestamp} from '../../clock'; import type * as types from './types'; diff --git a/src/json-crdt-patch/util/binary/CrdtReader.ts b/src/json-crdt-patch/util/binary/CrdtReader.ts index 32a788df43..242a75e36c 100644 --- a/src/json-crdt-patch/util/binary/CrdtReader.ts +++ b/src/json-crdt-patch/util/binary/CrdtReader.ts @@ -1,4 +1,4 @@ -import {Reader} from '../../../util/buffers/Reader'; +import {Reader} from '@jsonjoy.com/json-pack/lib/util/buffers/Reader'; /** @todo Rename file name. */ export class CrdtReader extends Reader { diff --git a/src/json-crdt-patch/util/binary/CrdtWriter.ts b/src/json-crdt-patch/util/binary/CrdtWriter.ts index a0476a608c..5c71546451 100644 --- a/src/json-crdt-patch/util/binary/CrdtWriter.ts +++ b/src/json-crdt-patch/util/binary/CrdtWriter.ts @@ -1,4 +1,4 @@ -import {Writer} from '../../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; export class CrdtWriter extends Writer { /** diff --git a/src/json-crdt/__bench__/util/concurrent-trace.ts b/src/json-crdt/__bench__/util/concurrent-trace.ts index 15f1fac4f7..333a950d3f 100644 --- a/src/json-crdt/__bench__/util/concurrent-trace.ts +++ b/src/json-crdt/__bench__/util/concurrent-trace.ts @@ -1,8 +1,8 @@ import * as path from 'path'; import * as fs from 'fs'; import {Patch} from '../../../json-crdt-patch'; -import {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; -import {JsonDecoder} from '../../../json-pack/json/JsonDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; export const loadConcurrentTrace = (traceName: string): [batch: Patch[], view: unknown] => { const root = path.resolve(__dirname, '..', '..', '..', '..'); diff --git a/src/json-crdt/__bench__/util/fuzzer-traces.ts b/src/json-crdt/__bench__/util/fuzzer-traces.ts index d0bc81b5c6..a359a1fd47 100644 --- a/src/json-crdt/__bench__/util/fuzzer-traces.ts +++ b/src/json-crdt/__bench__/util/fuzzer-traces.ts @@ -1,9 +1,9 @@ import * as path from 'path'; import * as fs from 'fs'; import {Patch} from '../../../json-crdt-patch'; -import {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {Model} from '../../model'; -import {bufferToUint8Array} from '../../../util/buffers/bufferToUint8Array'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; export const loadFuzzerTrace = (traceName: string): [batch: Patch[], model: Model] => { const root = path.resolve(__dirname, '..', '..', '..', '..'); diff --git a/src/json-crdt/codec/indexed/binary/Decoder.ts b/src/json-crdt/codec/indexed/binary/Decoder.ts index 0d9fe1c01f..e419c411d1 100644 --- a/src/json-crdt/codec/indexed/binary/Decoder.ts +++ b/src/json-crdt/codec/indexed/binary/Decoder.ts @@ -4,7 +4,7 @@ import {CrdtReader} from '../../../../json-crdt-patch/util/binary/CrdtReader'; import {IndexedFields, FieldName, IndexedNodeFields} from './types'; import {ITimestampStruct, IClockVector, Timestamp, ClockVector} from '../../../../json-crdt-patch/clock'; import {Model, UNDEFINED} from '../../../model/Model'; -import {CborDecoderBase} from '../../../../json-pack/cbor/CborDecoderBase'; +import {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase'; import {CRDT_MAJOR} from '../../structural/binary/constants'; export class Decoder { diff --git a/src/json-crdt/codec/indexed/binary/Encoder.ts b/src/json-crdt/codec/indexed/binary/Encoder.ts index 01b158f1dd..3d3c5d55eb 100644 --- a/src/json-crdt/codec/indexed/binary/Encoder.ts +++ b/src/json-crdt/codec/indexed/binary/Encoder.ts @@ -1,7 +1,7 @@ import {ITimestampStruct, Timestamp} from '../../../../json-crdt-patch/clock'; import {ClockTable} from '../../../../json-crdt-patch/codec/clock/ClockTable'; import {CrdtWriter} from '../../../../json-crdt-patch/util/binary/CrdtWriter'; -import {CborEncoder} from '../../../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {Model} from '../../../model'; import * as nodes from '../../../nodes'; import {CRDT_MAJOR_OVERLAY} from '../../structural/binary/constants'; diff --git a/src/json-crdt/codec/sidecar/binary/Decoder.ts b/src/json-crdt/codec/sidecar/binary/Decoder.ts index 25b6e7689b..a7700e31cf 100644 --- a/src/json-crdt/codec/sidecar/binary/Decoder.ts +++ b/src/json-crdt/codec/sidecar/binary/Decoder.ts @@ -2,7 +2,7 @@ import {ClockDecoder} from '../../../../json-crdt-patch/codec/clock/ClockDecoder import {CrdtReader} from '../../../../json-crdt-patch/util/binary/CrdtReader'; import {ITimestampStruct} from '../../../../json-crdt-patch/clock'; import {Model, UNDEFINED} from '../../../model/Model'; -import {CborDecoderBase} from '../../../../json-pack/cbor/CborDecoderBase'; +import {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase'; import * as nodes from '../../../nodes'; import {CRDT_MAJOR} from '../../structural/binary/constants'; import {sort} from '../../../../util/sort/insertion'; diff --git a/src/json-crdt/codec/sidecar/binary/Encoder.ts b/src/json-crdt/codec/sidecar/binary/Encoder.ts index f937ae7ef5..3dd3afdb84 100644 --- a/src/json-crdt/codec/sidecar/binary/Encoder.ts +++ b/src/json-crdt/codec/sidecar/binary/Encoder.ts @@ -2,10 +2,10 @@ import * as nodes from '../../../nodes'; import {ClockEncoder} from '../../../../json-crdt-patch/codec/clock/ClockEncoder'; import {CrdtWriter} from '../../../../json-crdt-patch/util/binary/CrdtWriter'; import {ITimestampStruct, Timestamp} from '../../../../json-crdt-patch/clock'; -import {CborEncoder} from '../../../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {SESSION} from '../../../../json-crdt-patch/constants'; import {CRDT_MAJOR_OVERLAY} from '../../structural/binary/constants'; -import {sort} from '../../../../util/sort/insertion'; +import {sort} from '@jsonjoy.com/json-pack/lib/util/sort/insertion'; import {UNDEFINED} from '../../../model/Model'; import type {Model} from '../../../model'; diff --git a/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts b/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts index d04720cb45..c9c90a178d 100644 --- a/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts +++ b/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts @@ -1,5 +1,5 @@ import {s} from '../../../../../json-crdt-patch'; -import {CborDecoder} from '../../../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {Model} from '../../../../model'; import {Encoder} from '../Encoder'; import {Decoder} from '../Decoder'; diff --git a/src/json-crdt/codec/sidecar/binary/__tests__/all-types-smoketest.spec.ts b/src/json-crdt/codec/sidecar/binary/__tests__/all-types-smoketest.spec.ts index f679991c9d..26be210bb6 100644 --- a/src/json-crdt/codec/sidecar/binary/__tests__/all-types-smoketest.spec.ts +++ b/src/json-crdt/codec/sidecar/binary/__tests__/all-types-smoketest.spec.ts @@ -2,7 +2,7 @@ import {Model} from '../../../../model'; import {runCodecAllTypesSmokeTests} from '../../../structural/verbose/__tests__/runCodecAllTypesSmokeTests'; import {Encoder} from '../Encoder'; import {Decoder} from '../Decoder'; -import {CborDecoder} from '../../../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; const encoder = new Encoder(); const decoder = new Decoder(); diff --git a/src/json-crdt/codec/sidecar/binary/__tests__/automated-logical.spec.ts b/src/json-crdt/codec/sidecar/binary/__tests__/automated-logical.spec.ts index e7e07cfa9b..637296a5d4 100644 --- a/src/json-crdt/codec/sidecar/binary/__tests__/automated-logical.spec.ts +++ b/src/json-crdt/codec/sidecar/binary/__tests__/automated-logical.spec.ts @@ -4,7 +4,7 @@ import {Encoder} from '../Encoder'; import {Decoder} from '../Decoder'; import {documents} from '../../../../../__tests__/json-documents'; import {binaryDocuments} from '../../../../../__tests__/binary-documents'; -import {CborDecoder} from '../../../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; for (const {name, json} of [...documents, ...binaryDocuments]) { describe('fresh encoder and decoder', () => { diff --git a/src/json-crdt/codec/sidecar/binary/__tests__/fuzzer-logical.spec.ts b/src/json-crdt/codec/sidecar/binary/__tests__/fuzzer-logical.spec.ts index 315b63d0bd..6812c84275 100644 --- a/src/json-crdt/codec/sidecar/binary/__tests__/fuzzer-logical.spec.ts +++ b/src/json-crdt/codec/sidecar/binary/__tests__/fuzzer-logical.spec.ts @@ -1,7 +1,7 @@ import {JsonCrdtFuzzer} from '../../../../__tests__/fuzzer/JsonCrdtFuzzer'; import {Encoder} from '../Encoder'; import {Decoder} from '../Decoder'; -import {CborDecoder} from '../../../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; const encoder = new Encoder(); const decoder = new Decoder(); diff --git a/src/json-crdt/codec/structural/binary/Decoder.ts b/src/json-crdt/codec/structural/binary/Decoder.ts index 1de5d32c76..bda7c00f5e 100644 --- a/src/json-crdt/codec/structural/binary/Decoder.ts +++ b/src/json-crdt/codec/structural/binary/Decoder.ts @@ -3,7 +3,7 @@ import {ClockDecoder} from '../../../../json-crdt-patch/codec/clock/ClockDecoder import {CrdtReader} from '../../../../json-crdt-patch/util/binary/CrdtReader'; import {ITimestampStruct, Timestamp} from '../../../../json-crdt-patch/clock'; import {Model, UNDEFINED} from '../../../model/Model'; -import {CborDecoderBase} from '../../../../json-pack/cbor/CborDecoderBase'; +import {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase'; import {SESSION} from '../../../../json-crdt-patch/constants'; import {CRDT_MAJOR} from './constants'; diff --git a/src/json-crdt/codec/structural/binary/Encoder.ts b/src/json-crdt/codec/structural/binary/Encoder.ts index 9734da685e..36ae0ffb14 100644 --- a/src/json-crdt/codec/structural/binary/Encoder.ts +++ b/src/json-crdt/codec/structural/binary/Encoder.ts @@ -2,7 +2,7 @@ import * as nodes from '../../../nodes'; import {ClockEncoder} from '../../../../json-crdt-patch/codec/clock/ClockEncoder'; import {CrdtWriter} from '../../../../json-crdt-patch/util/binary/CrdtWriter'; import {ITimestampStruct, Timestamp} from '../../../../json-crdt-patch/clock'; -import {CborEncoder} from '../../../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {SESSION} from '../../../../json-crdt-patch/constants'; import {CRDT_MAJOR_OVERLAY} from './constants'; import type {Model} from '../../../model'; diff --git a/src/json-crdt/codec/structural/binary/ViewDecoder.ts b/src/json-crdt/codec/structural/binary/ViewDecoder.ts index 187a447ede..cf60879c0b 100644 --- a/src/json-crdt/codec/structural/binary/ViewDecoder.ts +++ b/src/json-crdt/codec/structural/binary/ViewDecoder.ts @@ -1,5 +1,5 @@ +import {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase'; import {CrdtReader} from '../../../../json-crdt-patch/util/binary/CrdtReader'; -import {CborDecoderBase} from '../../../../json-pack/cbor/CborDecoderBase'; import {CRDT_MAJOR} from './constants'; export class ViewDecoder extends CborDecoderBase { diff --git a/src/json-crdt/codec/structural/compact-binary/Decoder.ts b/src/json-crdt/codec/structural/compact-binary/Decoder.ts index d3708ba0c0..72d66af5e1 100644 --- a/src/json-crdt/codec/structural/compact-binary/Decoder.ts +++ b/src/json-crdt/codec/structural/compact-binary/Decoder.ts @@ -1,5 +1,5 @@ import {Decoder as CompactDecoder} from '../compact/Decoder'; -import {decoder} from '../../../../json-pack/msgpack/util'; +import {decoder} from '@jsonjoy.com/json-pack/lib/msgpack/util'; import {Model} from '../../../model'; export class Decoder { diff --git a/src/json-crdt/codec/structural/compact-binary/Encoder.ts b/src/json-crdt/codec/structural/compact-binary/Encoder.ts index 55d8f001fa..0aabb7594f 100644 --- a/src/json-crdt/codec/structural/compact-binary/Encoder.ts +++ b/src/json-crdt/codec/structural/compact-binary/Encoder.ts @@ -1,5 +1,5 @@ import {Encoder as CompactEncoder} from '../compact/Encoder'; -import {encoderFull} from '../../../../json-pack/msgpack/util'; +import {encoderFull} from '@jsonjoy.com/json-pack/lib/msgpack/util'; import {Model} from '../../../model'; export class Encoder { diff --git a/src/json-crdt/codec/structural/verbose/Decoder.ts b/src/json-crdt/codec/structural/verbose/Decoder.ts index ce51d0b3d9..0e140edd9e 100644 --- a/src/json-crdt/codec/structural/verbose/Decoder.ts +++ b/src/json-crdt/codec/structural/verbose/Decoder.ts @@ -1,5 +1,5 @@ import * as nodes from '../../../nodes'; -import {fromBase64} from '../../../../util/base64/fromBase64'; +import {fromBase64} from '@jsonjoy.com/base64/lib/fromBase64'; import {ITimestampStruct, ts, ClockVector} from '../../../../json-crdt-patch/clock'; import {Model} from '../../../model'; import {SESSION} from '../../../../json-crdt-patch/constants'; diff --git a/src/json-crdt/codec/structural/verbose/Encoder.ts b/src/json-crdt/codec/structural/verbose/Encoder.ts index 34231ad036..99165cbc8f 100644 --- a/src/json-crdt/codec/structural/verbose/Encoder.ts +++ b/src/json-crdt/codec/structural/verbose/Encoder.ts @@ -1,5 +1,5 @@ import * as nodes from '../../../nodes'; -import {toBase64} from '../../../../util/base64/toBase64'; +import {toBase64} from '@jsonjoy.com/base64/lib/toBase64'; import {SESSION} from '../../../../json-crdt-patch/constants'; import {ITimestampStruct, IClockVector, Timestamp} from '../../../../json-crdt-patch/clock'; import {Model} from '../../../model'; diff --git a/src/json-crdt/history/LocalHistoryCrud.ts b/src/json-crdt/history/LocalHistoryCrud.ts index b19ba39140..7baf866950 100644 --- a/src/json-crdt/history/LocalHistoryCrud.ts +++ b/src/json-crdt/history/LocalHistoryCrud.ts @@ -1,5 +1,5 @@ -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; -import {CborDecoder} from '../../json-pack/cbor/CborDecoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {LogEncoder} from '../log/codec/LogEncoder'; import {LogDecoder} from '../log/codec/LogDecoder'; import type {CrudApi} from 'memfs/lib/crud/types'; diff --git a/src/json-crdt/log/codec/LogDecoder.ts b/src/json-crdt/log/codec/LogDecoder.ts index d47d651947..132ad539cd 100644 --- a/src/json-crdt/log/codec/LogDecoder.ts +++ b/src/json-crdt/log/codec/LogDecoder.ts @@ -4,8 +4,8 @@ import {Patch} from '../../../json-crdt-patch'; import {FileModelEncoding} from './constants'; import {SESSION} from '../../../json-crdt-patch/constants'; import type * as types from './types'; -import type {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; -import type {JsonDecoder} from '../../../json-pack/json/JsonDecoder'; +import type {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; +import type {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; import type {Decoder as SidecarDecoder} from '../../codec/sidecar/binary/Decoder'; import type {Decoder as StructuralDecoderCompact} from '../../codec/structural/compact/Decoder'; import type {Decoder as StructuralDecoderVerbose} from '../../codec/structural/verbose/Decoder'; diff --git a/src/json-crdt/log/codec/LogEncoder.ts b/src/json-crdt/log/codec/LogEncoder.ts index 03330daef9..fdad92794f 100644 --- a/src/json-crdt/log/codec/LogEncoder.ts +++ b/src/json-crdt/log/codec/LogEncoder.ts @@ -1,8 +1,8 @@ import {Log} from '../Log'; import {FileModelEncoding} from './constants'; import type * as types from './types'; -import type {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import type {JsonEncoder} from '../../../json-pack/json/JsonEncoder'; +import type {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import type {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import type {Encoder as StructuralEncoderCompact} from '../../codec/structural/compact/Encoder'; import type {Encoder as StructuralEncoderVerbose} from '../../codec/structural/verbose/Encoder'; import type {Encoder as SidecarEncoder} from '../../codec/sidecar/binary/Encoder'; diff --git a/src/json-crdt/log/codec/__tests__/LogEncoder.spec.ts b/src/json-crdt/log/codec/__tests__/LogEncoder.spec.ts index dd090288c9..b5781dbe12 100644 --- a/src/json-crdt/log/codec/__tests__/LogEncoder.spec.ts +++ b/src/json-crdt/log/codec/__tests__/LogEncoder.spec.ts @@ -1,10 +1,10 @@ // import {s} from '../../../json-crdt-patch'; import {Model} from '../../../model'; -import {JsonDecoder} from '../../../../json-pack/json/JsonDecoder'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; import {logEncoderOpts} from '../logEncoderOpts'; import {LogEncoder} from '../LogEncoder'; import {Log} from '../../Log'; -import {CborDecoder} from '../../../../json-pack/cbor/CborDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; const setup = (view: unknown) => { const model = Model.withServerClock(); diff --git a/src/json-crdt/log/codec/logDecoderOpts.ts b/src/json-crdt/log/codec/logDecoderOpts.ts index 9fe19a5089..8be9cfcde4 100644 --- a/src/json-crdt/log/codec/logDecoderOpts.ts +++ b/src/json-crdt/log/codec/logDecoderOpts.ts @@ -1,8 +1,8 @@ import {Decoder as SidecarDecoder} from '../../codec/sidecar/binary/Decoder'; import {Decoder as StructuralDecoderCompact} from '../../codec/structural/compact/Decoder'; import {Decoder as StructuralDecoderVerbose} from '../../codec/structural/verbose/Decoder'; -import {JsonDecoder} from '../../../json-pack/json/JsonDecoder'; -import {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {decode as decodeCompact} from '../../../json-crdt-patch/codec/compact/decode'; import {decode as decodeVerbose} from '../../../json-crdt-patch/codec/verbose/decode'; import type {LogDecoderOpts} from './LogDecoder'; diff --git a/src/json-crdt/log/codec/logEncoderOpts.ts b/src/json-crdt/log/codec/logEncoderOpts.ts index 76f50d66d5..b826ed468f 100644 --- a/src/json-crdt/log/codec/logEncoderOpts.ts +++ b/src/json-crdt/log/codec/logEncoderOpts.ts @@ -1,11 +1,11 @@ -import {Writer} from '../../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {Encoder as SidecarEncoder} from '../../codec/sidecar/binary/Encoder'; import {Encoder as StructuralEncoderCompact} from '../../codec/structural/compact/Encoder'; import {Encoder as StructuralEncoderVerbose} from '../../codec/structural/verbose/Encoder'; import {encode as encodeCompact} from '../../../json-crdt-patch/codec/compact/encode'; import {encode as encodeVerbose} from '../../../json-crdt-patch/codec/verbose/encode'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import {JsonEncoder} from '../../../json-pack/json/JsonEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import type {LogEncoderOpts} from './LogEncoder'; const writer = new Writer(4096); diff --git a/src/json-crdt/nodes/rga/AbstractRga.ts b/src/json-crdt/nodes/rga/AbstractRga.ts index 909b15a45a..443cb33610 100644 --- a/src/json-crdt/nodes/rga/AbstractRga.ts +++ b/src/json-crdt/nodes/rga/AbstractRga.ts @@ -8,14 +8,14 @@ import { containsId, Timestamp, } from '../../../json-crdt-patch/clock'; -import {isUint8Array} from '../../../util/buffers/isUint8Array'; +import {isUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/isUint8Array'; import {rSplay, lSplay, llSplay, rrSplay, lrSplay, rlSplay} from '../../../util/trees/splay/util'; import {splay2} from '../../../util/trees/splay/util2'; import {insert2, remove2} from '../../../util/trees/util2'; import {ORIGIN} from '../../../json-crdt-patch/constants'; import {printTree} from '../../../util/print/printTree'; import {printBinary} from '../../../util/print/printBinary'; -import {printOctets} from '../../../util/buffers/printOctets'; +import {printOctets} from '@jsonjoy.com/json-pack/lib/util/buffers/printOctets'; /** * @category CRDT Node diff --git a/src/json-crdt/schema/__tests__/toSchema.spec.ts b/src/json-crdt/schema/__tests__/toSchema.spec.ts index 4850337d4f..a0ae310343 100644 --- a/src/json-crdt/schema/__tests__/toSchema.spec.ts +++ b/src/json-crdt/schema/__tests__/toSchema.spec.ts @@ -1,6 +1,6 @@ import {NodeBuilder, s, nodes} from '../../../json-crdt-patch'; import {deepEqual} from '../../../json-equal/deepEqual'; -import {cmpUint8Array} from '../../../util/buffers/cmpUint8Array'; +import {cmpUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/cmpUint8Array'; import {Model} from '../../model'; import {toSchema} from '../toSchema'; diff --git a/src/json-equal/$$deepEqual/v1.ts b/src/json-equal/$$deepEqual/v1.ts index 87a2c349bd..a240f9171c 100644 --- a/src/json-equal/$$deepEqual/v1.ts +++ b/src/json-equal/$$deepEqual/v1.ts @@ -1,4 +1,4 @@ -import {JavaScript} from '../../util/codegen'; +import {JavaScript} from '@jsonjoy.com/json-pack/lib/util/codegen'; const codegenValue = (doc: unknown, code: string[], r: number): number => { let rr = r; diff --git a/src/json-expression/codegen.ts b/src/json-expression/codegen.ts index 38de6526e1..b4427251ea 100644 --- a/src/json-expression/codegen.ts +++ b/src/json-expression/codegen.ts @@ -1,8 +1,8 @@ import * as util from './util'; -import {Codegen} from '../util/codegen/Codegen'; +import {Codegen} from '@jsonjoy.com/json-pack/lib/util/codegen/Codegen'; import {ExpressionResult, Literal} from './codegen-steps'; import {createEvaluate} from './createEvaluate'; -import {JavaScript} from '../util/codegen'; +import {JavaScript} from '@jsonjoy.com/json-pack/lib/util/codegen'; import {Vars} from './Vars'; import type * as types from './types'; diff --git a/src/json-hash/index.ts b/src/json-hash/index.ts index 85a3d9fe34..80dcc9c879 100644 --- a/src/json-hash/index.ts +++ b/src/json-hash/index.ts @@ -1,4 +1,4 @@ -import type {JsonValue} from '../json-pack/types'; +import type {JsonValue} from '@jsonjoy.com/json-pack/lib/types'; import {sort} from '../util/sort/insertion'; export const enum CONST { diff --git a/src/json-pack/JsonPackExtension.ts b/src/json-pack/JsonPackExtension.ts deleted file mode 100644 index e21ca138ae..0000000000 --- a/src/json-pack/JsonPackExtension.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * A wrapping for MessagePack extension or CBOR tag value. When encoder - * encounters {@link JsonPackExtension} it will encode it as a MessagePack - * extension or CBOR tag. Likewise, the decoder will - * decode extensions into {@link JsonPackExtension}. - * - * @category Value - */ -export class JsonPackExtension { - constructor( - public readonly tag: number, - public readonly val: T, - ) {} -} diff --git a/src/json-pack/JsonPackValue.ts b/src/json-pack/JsonPackValue.ts deleted file mode 100644 index cdf7f41dec..0000000000 --- a/src/json-pack/JsonPackValue.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Use this wrapper is you have a pre-encoded MessagePack or CBOR value and you would - * like to dump it into a the document as-is. The contents of `buf` will - * be written as is to the document. - * - * It also serves as CBOR simple value container. In which case the type of value - * `val` field is "number". - * - * @category Value - */ -export class JsonPackValue { - constructor(public readonly val: T) {} -} diff --git a/src/json-pack/README.md b/src/json-pack/README.md deleted file mode 100644 index 3e287204e1..0000000000 --- a/src/json-pack/README.md +++ /dev/null @@ -1,426 +0,0 @@ -# `json-pack`—JSON binary packing - -This library contains implementations of various JSON codecs into binary, -formats, such as MessagePack, CBOR, and Amazon Ion. - - -`json-pack` implements the fastest encoders and decoders for MessagePack and CBOR. - -- [__MessagePack__](./msgpack/README.md) -- [__CBOR__](./cbor/README.md) - - -## Benchmarks - -Encoding: - -``` -npx ts-node benchmarks/json-pack/bench.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.0.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Small object, 44 bytes -🤞 json-joy/json-pack JsonEncoder x 5,385,617 ops/sec ±0.53% (100 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 2,254,954 ops/sec ±0.83% (97 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 5,953,159 ops/sec ±1.12% (92 runs sampled) -🤞 json-joy/json-pack CborEncoder x 6,248,036 ops/sec ±0.29% (98 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 3,121,940 ops/sec ±0.16% (99 runs sampled) -🤞 JSON.stringify() x 3,866,116 ops/sec ±0.11% (101 runs sampled) -🤞 @msgpack/msgpack x 1,406,546 ops/sec ±0.94% (93 runs sampled) -🤞 msgpackr x 2,404,916 ops/sec ±3.22% (86 runs sampled) -🤞 cbor-x x 4,737,433 ops/sec ±1.00% (97 runs sampled) -🤞 msgpack-lite x 987,201 ops/sec ±2.84% (91 runs sampled) -🤞 msgpack5 x 197,867 ops/sec ±3.65% (84 runs sampled) -🤞 messagepack x 171,865 ops/sec ±4.44% (74 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -🤞 json-joy/json-pack JsonEncoder x 299,970 ops/sec ±0.30% (97 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 211,651 ops/sec ±0.18% (100 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 429,535 ops/sec ±3.38% (93 runs sampled) -🤞 json-joy/json-pack CborEncoder x 428,848 ops/sec ±0.71% (97 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 322,982 ops/sec ±0.67% (97 runs sampled) -🤞 JSON.stringify() x 306,828 ops/sec ±1.94% (90 runs sampled) -🤞 @msgpack/msgpack x 199,937 ops/sec ±5.52% (93 runs sampled) -🤞 msgpackr x 317,457 ops/sec ±2.18% (90 runs sampled) -🤞 cbor-x x 401,854 ops/sec ±3.20% (92 runs sampled) -🤞 msgpack-lite x 135,110 ops/sec ±1.29% (94 runs sampled) -🤞 msgpack5 x 15,217 ops/sec ±3.72% (85 runs sampled) -🤞 messagepack x 13,853 ops/sec ±4.73% (71 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -🤞 json-joy/json-pack JsonEncoder x 87,312 ops/sec ±1.10% (96 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 64,718 ops/sec ±0.45% (96 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 134,615 ops/sec ±0.19% (97 runs sampled) -🤞 json-joy/json-pack CborEncoder x 128,975 ops/sec ±0.20% (98 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 103,325 ops/sec ±1.62% (98 runs sampled) -🤞 JSON.stringify() x 101,067 ops/sec ±1.36% (95 runs sampled) -🤞 @msgpack/msgpack x 61,715 ops/sec ±0.22% (98 runs sampled) -🤞 msgpackr x 95,175 ops/sec ±3.84% (95 runs sampled) -🤞 cbor-x x 111,658 ops/sec ±1.34% (95 runs sampled) -🤞 msgpack-lite x 41,364 ops/sec ±0.28% (100 runs sampled) -🤞 msgpack5 x 3,262 ops/sec ±4.32% (71 runs sampled) -🤞 messagepack x 4,167 ops/sec ±7.29% (65 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------- Very large object, 45750 bytes -🤞 json-joy/json-pack JsonEncoder x 5,687 ops/sec ±1.92% (94 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 5,813 ops/sec ±2.51% (97 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 5,749 ops/sec ±0.67% (98 runs sampled) -🤞 json-joy/json-pack CborEncoder x 5,515 ops/sec ±0.70% (98 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 5,027 ops/sec ±0.19% (100 runs sampled) -🤞 JSON.stringify() x 7,687 ops/sec ±0.87% (99 runs sampled) -🤞 @msgpack/msgpack x 3,379 ops/sec ±2.20% (97 runs sampled) -🤞 msgpackr x 5,929 ops/sec ±15.26% (96 runs sampled) -🤞 cbor-x x 5,032 ops/sec ±5.17% (90 runs sampled) -🤞 msgpack-lite x 2,173 ops/sec ±1.17% (97 runs sampled) -🤞 msgpack5 x 179 ops/sec ±2.95% (68 runs sampled) -🤞 messagepack x 167 ops/sec ±1.09% (79 runs sampled) -Fastest is 🤞 JSON.stringify() ------------------------------------------------------------------- Object with many keys, 969 bytes -🤞 json-joy/json-pack JsonEncoder x 213,447 ops/sec ±3.31% (95 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 168,303 ops/sec ±2.13% (95 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 275,511 ops/sec ±0.40% (95 runs sampled) -🤞 json-joy/json-pack CborEncoder x 270,949 ops/sec ±0.32% (97 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 210,525 ops/sec ±0.66% (99 runs sampled) -🤞 JSON.stringify() x 200,767 ops/sec ±0.19% (101 runs sampled) -🤞 @msgpack/msgpack x 163,665 ops/sec ±0.81% (98 runs sampled) -🤞 msgpackr x 151,889 ops/sec ±0.27% (96 runs sampled) -🤞 cbor-x x 191,010 ops/sec ±0.44% (96 runs sampled) -🤞 msgpack-lite x 93,537 ops/sec ±0.68% (99 runs sampled) -🤞 msgpack5 x 28,581 ops/sec ±1.74% (93 runs sampled) -🤞 messagepack x 8,330 ops/sec ±5.00% (61 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast -------------------------------------------------------------------------- String ladder, 3398 bytes -🤞 json-joy/json-pack JsonEncoder x 147,755 ops/sec ±0.23% (97 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 128,378 ops/sec ±0.15% (96 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 298,037 ops/sec ±0.73% (98 runs sampled) -🤞 json-joy/json-pack CborEncoder x 293,608 ops/sec ±0.22% (97 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 244,864 ops/sec ±3.92% (92 runs sampled) -🤞 JSON.stringify() x 165,819 ops/sec ±1.72% (94 runs sampled) -🤞 @msgpack/msgpack x 79,127 ops/sec ±1.43% (93 runs sampled) -🤞 msgpackr x 236,254 ops/sec ±1.45% (94 runs sampled) -🤞 cbor-x x 206,835 ops/sec ±1.26% (92 runs sampled) -🤞 msgpack-lite x 157,499 ops/sec ±0.39% (98 runs sampled) -🤞 msgpack5 x 55,363 ops/sec ±2.75% (88 runs sampled) -🤞 messagepack x 8,261 ops/sec ±2.97% (72 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------------- Long strings, 7011 bytes -🤞 json-joy/json-pack JsonEncoder x 51,334 ops/sec ±0.16% (99 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 27,108 ops/sec ±4.89% (90 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 374,042 ops/sec ±6.39% (91 runs sampled) -🤞 json-joy/json-pack CborEncoder x 424,864 ops/sec ±0.35% (97 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 363,465 ops/sec ±1.91% (85 runs sampled) -🤞 JSON.stringify() x 59,793 ops/sec ±0.14% (100 runs sampled) -🤞 @msgpack/msgpack x 57,373 ops/sec ±0.13% (98 runs sampled) -🤞 msgpackr x 372,751 ops/sec ±2.17% (90 runs sampled) -🤞 cbor-x x 389,277 ops/sec ±1.60% (93 runs sampled) -🤞 msgpack-lite x 170,279 ops/sec ±0.82% (97 runs sampled) -🤞 msgpack5 x 83,809 ops/sec ±2.80% (83 runs sampled) -🤞 messagepack x 20,076 ops/sec ±1.45% (87 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -🤞 json-joy/json-pack JsonEncoder x 1,577,757 ops/sec ±0.16% (98 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,057,420 ops/sec ±0.38% (100 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 1,844,775 ops/sec ±0.20% (100 runs sampled) -🤞 json-joy/json-pack CborEncoder x 1,468,011 ops/sec ±0.23% (98 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 1,240,577 ops/sec ±0.19% (98 runs sampled) -🤞 JSON.stringify() x 1,852,916 ops/sec ±0.20% (100 runs sampled) -🤞 @msgpack/msgpack x 781,414 ops/sec ±0.42% (92 runs sampled) -🤞 msgpackr x 1,672,474 ops/sec ±0.23% (99 runs sampled) -🤞 cbor-x x 1,351,338 ops/sec ±0.20% (97 runs sampled) -🤞 msgpack-lite x 416,300 ops/sec ±0.76% (96 runs sampled) -🤞 msgpack5 x 151,657 ops/sec ±1.97% (91 runs sampled) -🤞 messagepack x 35,124 ops/sec ±5.60% (61 runs sampled) -Fastest is 🤞 JSON.stringify() --------------------------------------------------------------------------------- Numbers, 136 bytes -🤞 json-joy/json-pack JsonEncoder x 1,708,133 ops/sec ±1.09% (98 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,135,630 ops/sec ±1.67% (95 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 2,658,037 ops/sec ±1.33% (97 runs sampled) -🤞 json-joy/json-pack CborEncoder x 3,084,914 ops/sec ±0.24% (101 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 1,620,958 ops/sec ±2.15% (94 runs sampled) -🤞 JSON.stringify() x 1,602,303 ops/sec ±0.24% (98 runs sampled) -🤞 @msgpack/msgpack x 997,885 ops/sec ±1.70% (97 runs sampled) -🤞 msgpackr x 2,659,862 ops/sec ±0.51% (96 runs sampled) -🤞 cbor-x x 3,116,954 ops/sec ±0.89% (95 runs sampled) -🤞 msgpack-lite x 892,281 ops/sec ±2.19% (92 runs sampled) -🤞 msgpack5 x 144,567 ops/sec ±3.06% (88 runs sampled) -🤞 messagepack x 383,134 ops/sec ±2.95% (74 runs sampled) -Fastest is 🤞 cbor-x ---------------------------------------------------------------------------------- Tokens, 308 bytes -🤞 json-joy/json-pack JsonEncoder x 1,370,517 ops/sec ±0.52% (98 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,016,856 ops/sec ±0.16% (93 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 1,347,193 ops/sec ±0.20% (96 runs sampled) -🤞 json-joy/json-pack CborEncoder x 1,353,358 ops/sec ±0.20% (101 runs sampled) -🤞 json-joy/json-pack MsgPackEncoderFast x 1,130,418 ops/sec ±0.14% (96 runs sampled) -🤞 JSON.stringify() x 1,549,669 ops/sec ±0.49% (97 runs sampled) -🤞 @msgpack/msgpack x 871,477 ops/sec ±0.92% (98 runs sampled) -🤞 msgpackr x 1,716,378 ops/sec ±0.20% (99 runs sampled) -🤞 cbor-x x 1,951,639 ops/sec ±0.16% (100 runs sampled) -🤞 msgpack-lite x 622,495 ops/sec ±1.03% (96 runs sampled) -🤞 msgpack5 x 81,727 ops/sec ±2.04% (91 runs sampled) -🤞 messagepack x 609,651 ops/sec ±1.64% (89 runs sampled) -Fastest is 🤞 cbor-x -``` - -Decoding: - -``` -node benchmarks/json-pack/bench.decoding.js -=============================================================================== Benchmark: Decoding -Warmup: 1000x , Node.js: v16.14.2 , Arch: arm64 , CPU: Apple M1 --------------------------------------------------------------------- Very large object, 45750 bytes -👍 JSON.parse() x 3,506 ops/sec ±0.19% (100 runs sampled) -👍 sjson.parse() x 3,336 ops/sec ±0.11% (99 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 4,915 ops/sec ±0.18% (100 runs sampled) -👍 cbor-x x 4,747 ops/sec ±0.15% (100 runs sampled) -👍 cbor x 260 ops/sec ±0.29% (90 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 5,506 ops/sec ±0.48% (100 runs sampled) -👍 msgpackr x 4,729 ops/sec ±0.23% (101 runs sampled) -👍 @msgpack/msgpack x 4,096 ops/sec ±0.25% (100 runs sampled) -👍 msgpack5 x 920 ops/sec ±0.34% (99 runs sampled) -👍 msgpack-lite x 1,223 ops/sec ±0.10% (100 runs sampled) -👍 messagepack x 194 ops/sec ±1.93% (73 runs sampled) -Fastest is 👍 json-joy/json-pack MsgPackDecoderFast --------------------------------------------------------------------------- Large object, 3741 bytes -👍 JSON.parse() x 91,582 ops/sec ±0.30% (100 runs sampled) -👍 sjson.parse() x 84,411 ops/sec ±0.16% (99 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 94,618 ops/sec ±0.27% (97 runs sampled) -👍 cbor-x x 108,102 ops/sec ±0.37% (101 runs sampled) -👍 cbor x 4,845 ops/sec ±0.79% (95 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 102,544 ops/sec ±0.39% (99 runs sampled) -👍 msgpackr x 111,668 ops/sec ±0.16% (101 runs sampled) -👍 @msgpack/msgpack x 56,952 ops/sec ±0.51% (97 runs sampled) -👍 msgpack5 x 17,420 ops/sec ±0.60% (101 runs sampled) -👍 msgpack-lite x 20,536 ops/sec ±0.23% (98 runs sampled) -👍 messagepack x 3,247 ops/sec ±2.30% (87 runs sampled) -Fastest is 👍 msgpackr -------------------------------------------------------------------------- Typical object, 993 bytes -👍 JSON.parse() x 304,670 ops/sec ±0.98% (97 runs sampled) -👍 sjson.parse() x 283,259 ops/sec ±0.20% (98 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 298,666 ops/sec ±0.19% (100 runs sampled) -👍 cbor-x x 322,995 ops/sec ±0.71% (97 runs sampled) -👍 cbor x 14,391 ops/sec ±0.88% (95 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 321,984 ops/sec ±0.23% (100 runs sampled) -👍 msgpackr x 328,671 ops/sec ±0.31% (99 runs sampled) -👍 @msgpack/msgpack x 198,604 ops/sec ±0.85% (96 runs sampled) -👍 msgpack5 x 51,549 ops/sec ±0.32% (99 runs sampled) -👍 msgpack-lite x 67,171 ops/sec ±0.19% (99 runs sampled) -👍 messagepack x 9,464 ops/sec ±1.95% (92 runs sampled) -Fastest is 👍 msgpackr ----------------------------------------------------------------------------- Small object, 44 bytes -👍 JSON.parse() x 2,654,389 ops/sec ±0.28% (98 runs sampled) -👍 sjson.parse() x 2,325,941 ops/sec ±0.21% (98 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 3,357,402 ops/sec ±0.31% (99 runs sampled) -👍 cbor-x x 4,133,737 ops/sec ±0.29% (101 runs sampled) -👍 cbor x 112,776 ops/sec ±5.79% (88 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 3,359,127 ops/sec ±0.56% (98 runs sampled) -👍 msgpackr x 3,436,592 ops/sec ±0.35% (97 runs sampled) -👍 @msgpack/msgpack x 2,288,251 ops/sec ±0.52% (94 runs sampled) -👍 msgpack5 x 377,061 ops/sec ±0.67% (96 runs sampled) -👍 msgpack-lite x 872,569 ops/sec ±0.31% (100 runs sampled) -👍 messagepack x 116,422 ops/sec ±1.84% (86 runs sampled) -Fastest is 👍 cbor-x ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 JSON.parse() x 270,312 ops/sec ±0.57% (98 runs sampled) -👍 sjson.parse() x 242,328 ops/sec ±3.10% (97 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 81,403 ops/sec ±0.42% (96 runs sampled) -👍 cbor-x x 93,131 ops/sec ±0.48% (99 runs sampled) -👍 cbor x 8,760 ops/sec ±0.93% (95 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 84,014 ops/sec ±0.31% (96 runs sampled) -👍 msgpackr x 91,477 ops/sec ±0.77% (90 runs sampled) -👍 @msgpack/msgpack x 73,089 ops/sec ±0.56% (89 runs sampled) -👍 msgpack5 x 23,468 ops/sec ±0.72% (97 runs sampled) -👍 msgpack-lite x 34,630 ops/sec ±0.48% (100 runs sampled) -👍 messagepack x 6,161 ops/sec ±1.77% (86 runs sampled) -Fastest is 👍 JSON.parse() -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 JSON.parse() x 287,387 ops/sec ±0.36% (99 runs sampled) -👍 sjson.parse() x 192,836 ops/sec ±0.40% (95 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 177,787 ops/sec ±0.48% (98 runs sampled) -👍 cbor-x x 320,303 ops/sec ±0.51% (94 runs sampled) -👍 cbor x 15,416 ops/sec ±0.61% (94 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 179,625 ops/sec ±0.59% (100 runs sampled) -👍 msgpackr x 375,452 ops/sec ±0.69% (94 runs sampled) -👍 @msgpack/msgpack x 36,544 ops/sec ±0.75% (84 runs sampled) -👍 msgpack5 x 54,428 ops/sec ±0.46% (98 runs sampled) -👍 msgpack-lite x 25,309 ops/sec ±0.81% (75 runs sampled) -👍 messagepack x 10,117 ops/sec ±3.99% (82 runs sampled) -Fastest is 👍 msgpackr --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 JSON.parse() x 117,335 ops/sec ±3.32% (89 runs sampled) -👍 sjson.parse() x 103,275 ops/sec ±0.64% (94 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 74,140 ops/sec ±7.50% (81 runs sampled) -👍 cbor-x x 92,753 ops/sec ±0.78% (96 runs sampled) -👍 cbor x 24,292 ops/sec ±27.70% (75 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 88,124 ops/sec ±1.65% (90 runs sampled) -👍 msgpackr x 94,352 ops/sec ±0.91% (94 runs sampled) -👍 @msgpack/msgpack x 33,256 ops/sec ±30.68% (71 runs sampled) -👍 msgpack5 x 68,367 ops/sec ±0.70% (95 runs sampled) -👍 msgpack-lite x 14,764 ops/sec ±2.04% (63 runs sampled) -👍 messagepack x 17,522 ops/sec ±28.57% (66 runs sampled) -Fastest is 👍 JSON.parse() --------------------------------------------------------------------------- Short strings, 170 bytes -👍 JSON.parse() x 1,077,084 ops/sec ±6.88% (77 runs sampled) -👍 sjson.parse() x 837,130 ops/sec ±2.70% (80 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 698,901 ops/sec ±4.69% (88 runs sampled) -👍 cbor-x x 1,182,303 ops/sec ±0.39% (94 runs sampled) -👍 cbor x 26,810 ops/sec ±14.70% (73 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 742,562 ops/sec ±5.06% (88 runs sampled) -👍 msgpackr x 1,041,143 ops/sec ±2.66% (85 runs sampled) -👍 @msgpack/msgpack x 440,652 ops/sec ±1.38% (92 runs sampled) -👍 msgpack5 x 133,387 ops/sec ±1.14% (96 runs sampled) -👍 msgpack-lite x 206,844 ops/sec ±0.63% (97 runs sampled) -👍 messagepack x 23,818 ops/sec ±2.13% (94 runs sampled) -Fastest is 👍 cbor-x,👍 JSON.parse() --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 JSON.parse() x 1,747,460 ops/sec ±0.61% (95 runs sampled) -👍 sjson.parse() x 1,553,635 ops/sec ±1.04% (93 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 2,289,002 ops/sec ±0.93% (87 runs sampled) -👍 cbor-x x 3,775,727 ops/sec ±2.86% (82 runs sampled) -👍 cbor x 77,650 ops/sec ±4.32% (83 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 2,287,682 ops/sec ±1.54% (80 runs sampled) -👍 msgpackr x 3,391,489 ops/sec ±0.59% (80 runs sampled) -👍 @msgpack/msgpack x 2,297,255 ops/sec ±1.54% (78 runs sampled) -👍 msgpack5 x 112,373 ops/sec ±1.19% (91 runs sampled) -👍 msgpack-lite x 1,378,387 ops/sec ±0.84% (95 runs sampled) -👍 messagepack x 1,174,740 ops/sec ±0.97% (89 runs sampled) -Fastest is 👍 cbor-x ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 JSON.parse() x 1,303,300 ops/sec ±2.26% (92 runs sampled) -👍 sjson.parse() x 1,091,921 ops/sec ±2.85% (86 runs sampled) -👍 json-joy/json-pack CborDecoderBase x 1,203,319 ops/sec ±2.12% (90 runs sampled) -👍 cbor-x x 1,787,591 ops/sec ±2.94% (74 runs sampled) -👍 cbor x 45,127 ops/sec ±24.11% (64 runs sampled) -👍 json-joy/json-pack MsgPackDecoderFast x 1,283,322 ops/sec ±1.93% (94 runs sampled) -👍 msgpackr x 1,890,533 ops/sec ±2.66% (90 runs sampled) -👍 @msgpack/msgpack x 1,364,025 ops/sec ±3.78% (67 runs sampled) -👍 msgpack5 x 117,205 ops/sec ±2.72% (90 runs sampled) -👍 msgpack-lite x 1,316,133 ops/sec ±0.74% (99 runs sampled) -👍 messagepack x 733,566 ops/sec ±1.55% (87 runs sampled) -Fastest is 👍 msgpackr -``` - -Encoder comparison: - -``` -npx ts-node benchmarks/json-pack/bench.encoders.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.2.0 , Arch: arm64 , CPU: Apple M1 Max ----------------------------------------------------------------------------- Small object, 44 bytes -👍 CborEncoderFast x 6,319,117 ops/sec ±0.11% (101 runs sampled) -👍 CborEncoder x 6,001,443 ops/sec ±0.15% (101 runs sampled) -👎 MsgPackEncoderFast x 6,047,466 ops/sec ±0.20% (99 runs sampled) -👎 MsgPackEncoder x 5,493,093 ops/sec ±0.10% (101 runs sampled) -👎 JsonEncoder x 6,018,890 ops/sec ±0.11% (97 runs sampled) -👎 UbjsonEncoder x 6,545,118 ops/sec ±0.10% (97 runs sampled) -👎 IonEncoderFast x 1,032,434 ops/sec ±0.14% (99 runs sampled) -👎 Buffer.from(JSON.stringify()) x 2,300,069 ops/sec ±0.15% (100 runs sampled) -Fastest is 👎 UbjsonEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -👍 CborEncoderFast x 460,125 ops/sec ±0.14% (98 runs sampled) -👍 CborEncoder x 439,506 ops/sec ±0.18% (98 runs sampled) -👎 MsgPackEncoderFast x 458,530 ops/sec ±0.15% (99 runs sampled) -👎 MsgPackEncoder x 449,540 ops/sec ±0.16% (100 runs sampled) -👎 JsonEncoder x 303,410 ops/sec ±0.12% (101 runs sampled) -👎 UbjsonEncoder x 479,450 ops/sec ±0.13% (99 runs sampled) -👎 IonEncoderFast x 68,000 ops/sec ±0.11% (102 runs sampled) -👎 Buffer.from(JSON.stringify()) x 207,747 ops/sec ±0.11% (98 runs sampled) -Fastest is 👎 UbjsonEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -👍 CborEncoderFast x 133,608 ops/sec ±0.15% (100 runs sampled) -👍 CborEncoder x 128,019 ops/sec ±0.13% (97 runs sampled) -👎 MsgPackEncoderFast x 133,863 ops/sec ±0.14% (99 runs sampled) -👎 MsgPackEncoder x 131,521 ops/sec ±0.18% (99 runs sampled) -👎 JsonEncoder x 93,018 ops/sec ±0.13% (98 runs sampled) -👎 UbjsonEncoder x 140,969 ops/sec ±0.15% (101 runs sampled) -👎 IonEncoderFast x 11,523 ops/sec ±0.15% (101 runs sampled) -👎 Buffer.from(JSON.stringify()) x 63,389 ops/sec ±0.13% (101 runs sampled) -Fastest is 👎 UbjsonEncoder --------------------------------------------------------------------- Very large object, 45750 bytes -👍 CborEncoderFast x 5,790 ops/sec ±0.15% (100 runs sampled) -👍 CborEncoder x 5,579 ops/sec ±0.14% (100 runs sampled) -👎 MsgPackEncoderFast x 6,005 ops/sec ±0.13% (100 runs sampled) -👎 MsgPackEncoder x 5,670 ops/sec ±0.18% (99 runs sampled) -👎 JsonEncoder x 6,351 ops/sec ±0.16% (101 runs sampled) -👎 UbjsonEncoder x 6,248 ops/sec ±0.18% (99 runs sampled) -👎 IonEncoderFast x 1,868 ops/sec ±0.21% (98 runs sampled) -👎 Buffer.from(JSON.stringify()) x 7,240 ops/sec ±0.19% (99 runs sampled) -Fastest is 👎 Buffer.from(JSON.stringify()) ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 CborEncoderFast x 283,371 ops/sec ±0.18% (99 runs sampled) -👍 CborEncoder x 268,056 ops/sec ±0.17% (96 runs sampled) -👎 MsgPackEncoderFast x 285,224 ops/sec ±0.17% (96 runs sampled) -👎 MsgPackEncoder x 272,416 ops/sec ±0.21% (98 runs sampled) -👎 JsonEncoder x 234,921 ops/sec ±0.21% (98 runs sampled) -👎 UbjsonEncoder x 292,228 ops/sec ±0.19% (95 runs sampled) -👎 IonEncoderFast x 63,456 ops/sec ±0.14% (98 runs sampled) -👎 Buffer.from(JSON.stringify()) x 175,341 ops/sec ±0.86% (93 runs sampled) -Fastest is 👎 UbjsonEncoder -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 CborEncoderFast x 280,167 ops/sec ±0.20% (100 runs sampled) -👍 CborEncoder x 283,404 ops/sec ±0.20% (97 runs sampled) -👎 MsgPackEncoderFast x 272,800 ops/sec ±0.18% (99 runs sampled) -👎 MsgPackEncoder x 283,433 ops/sec ±0.23% (98 runs sampled) -👎 JsonEncoder x 147,390 ops/sec ±0.16% (98 runs sampled) -👎 UbjsonEncoder x 290,624 ops/sec ±0.21% (98 runs sampled) -👎 IonEncoderFast x 25,452 ops/sec ±0.17% (101 runs sampled) -👎 Buffer.from(JSON.stringify()) x 145,352 ops/sec ±0.23% (99 runs sampled) -Fastest is 👎 UbjsonEncoder --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 CborEncoderFast x 394,386 ops/sec ±0.53% (95 runs sampled) -👍 CborEncoder x 394,442 ops/sec ±0.49% (94 runs sampled) -👎 MsgPackEncoderFast x 386,894 ops/sec ±0.54% (95 runs sampled) -👎 MsgPackEncoder x 394,019 ops/sec ±0.50% (95 runs sampled) -👎 JsonEncoder x 50,781 ops/sec ±0.13% (97 runs sampled) -👎 UbjsonEncoder x 396,184 ops/sec ±0.57% (95 runs sampled) -👎 IonEncoderFast x 11,799 ops/sec ±0.22% (99 runs sampled) -👎 Buffer.from(JSON.stringify()) x 28,742 ops/sec ±0.11% (102 runs sampled) -Fastest is 👎 UbjsonEncoder,👍 CborEncoder,👍 CborEncoderFast,👎 MsgPackEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -👍 CborEncoderFast x 1,816,742 ops/sec ±0.16% (100 runs sampled) -👍 CborEncoder x 1,831,503 ops/sec ±0.22% (97 runs sampled) -👎 MsgPackEncoderFast x 1,641,743 ops/sec ±0.17% (101 runs sampled) -👎 MsgPackEncoder x 1,694,803 ops/sec ±0.17% (97 runs sampled) -👎 JsonEncoder x 1,595,041 ops/sec ±0.12% (99 runs sampled) -👎 UbjsonEncoder x 1,779,112 ops/sec ±0.24% (98 runs sampled) -👎 IonEncoderFast x 422,031 ops/sec ±0.10% (101 runs sampled) -👎 Buffer.from(JSON.stringify()) x 1,001,976 ops/sec ±0.24% (98 runs sampled) -Fastest is 👍 CborEncoder --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 CborEncoderFast x 2,822,683 ops/sec ±0.14% (99 runs sampled) -👍 CborEncoder x 3,111,311 ops/sec ±0.20% (97 runs sampled) -👎 MsgPackEncoderFast x 2,918,971 ops/sec ±0.14% (100 runs sampled) -👎 MsgPackEncoder x 2,862,193 ops/sec ±0.13% (100 runs sampled) -👎 JsonEncoder x 1,706,584 ops/sec ±0.18% (96 runs sampled) -👎 UbjsonEncoder x 3,238,810 ops/sec ±0.15% (97 runs sampled) -👎 IonEncoderFast x 545,885 ops/sec ±0.16% (98 runs sampled) -👎 Buffer.from(JSON.stringify()) x 1,216,907 ops/sec ±0.20% (98 runs sampled) -Fastest is 👎 UbjsonEncoder ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 CborEncoderFast x 1,360,976 ops/sec ±0.20% (96 runs sampled) -👍 CborEncoder x 1,367,625 ops/sec ±0.16% (101 runs sampled) -👎 MsgPackEncoderFast x 1,753,202 ops/sec ±0.19% (99 runs sampled) -👎 MsgPackEncoder x 1,733,298 ops/sec ±0.16% (100 runs sampled) -👎 JsonEncoder x 1,411,382 ops/sec ±0.27% (98 runs sampled) -👎 UbjsonEncoder x 1,734,304 ops/sec ±0.17% (101 runs sampled) -👎 IonEncoderFast x 369,161 ops/sec ±0.21% (97 runs sampled) -👎 Buffer.from(JSON.stringify()) x 1,092,623 ops/sec ±0.15% (101 runs sampled) -Fastest is 👎 MsgPackEncoderFast -``` - - -### Shallow reading - -``` -node benchmarks/json-pack/bench.shallow-read.js -=============================================================================== Benchmark: Encoding -Warmup: 10000x , Node.js: v16.14.2 , Arch: arm64 , CPU: Apple M1 -------------------------------------------------------------------------- Typical object, 993 bytes -👍 JSON.parse() x 314,451 ops/sec ±0.24% (94 runs sampled) -👍 msgpackr x 332,628 ops/sec ±0.09% (99 runs sampled) -👍 cbor-x x 326,509 ops/sec ±0.05% (101 runs sampled) -👍 MsgPackDecoder x 368,088 ops/sec ±0.15% (100 runs sampled) -👍 CborDecoder x 327,286 ops/sec ±0.15% (101 runs sampled) -👍 MsgPackDecoder.{findKey,findIndex}() x 1,815,090 ops/sec ±0.07% (99 runs sampled) -👍 MsgPackDecoder.find() x 1,797,098 ops/sec ±0.15% (98 runs sampled) -👍 genShallowReader()(MsgPackDecoder) x 2,085,260 ops/sec ±0.19% (99 runs sampled) -Fastest is 👍 genShallowReader()(MsgPackDecoder) -``` diff --git a/src/json-pack/__bench__/bench.bson.encoding.ts b/src/json-pack/__bench__/bench.bson.encoding.ts deleted file mode 100644 index 1c4da8b3a4..0000000000 --- a/src/json-pack/__bench__/bench.bson.encoding.ts +++ /dev/null @@ -1,49 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.bson.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {BsonEncoder} from '../bson/BsonEncoder'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads as payloads_} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; -import {BSON, EJSON} from 'bson'; - -const payloads = payloads_.map((p) => ({...p, data: {data: p.data}})); - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const buf = Buffer.from(data as Uint8Array | Buffer); - const json = JSON.parse(buf.toString()); - return deepEqual(payload, json); - }, - runners: [ - { - name: 'json-joy/json-pack BsonEncoder', - setup: () => { - const writer = new Writer(); - const encoder = new BsonEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'bson BSON.serialize()', - setup: () => { - return (json: any) => { - return BSON.serialize(json); - }; - }, - }, - { - name: 'bson Buffer.from(EJSON.stringify())', - setup: () => { - return (json: any) => { - return Buffer.from(EJSON.stringify(json)); - }; - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.cbor-dag.encoding.ts b/src/json-pack/__bench__/bench.cbor-dag.encoding.ts deleted file mode 100644 index 7fd47a3c94..0000000000 --- a/src/json-pack/__bench__/bench.cbor-dag.encoding.ts +++ /dev/null @@ -1,57 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.cbor-dag.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoderDag} from '../cbor/CborEncoderDag'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: 'json-joy/json-pack CborEncoder', - setup: () => { - const encoder = new CborEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack CborEncoderDag', - setup: () => { - const encoder = new CborEncoderDag(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'cborg', - setup: () => { - const {encode} = require('cborg'); - return (json: any) => encode(json); - }, - }, - { - name: 'cbor-x', - setup: () => { - const {encode} = require('cbor-x'); - return (json: any) => encode(json); - }, - }, - { - name: 'Buffer.from(JSON.stringify)', - setup: () => { - return (json: any) => Buffer.from(JSON.stringify(json)); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.cbor.decoding.ts b/src/json-pack/__bench__/bench.cbor.decoding.ts deleted file mode 100644 index 58ec20e257..0000000000 --- a/src/json-pack/__bench__/bench.cbor.decoding.ts +++ /dev/null @@ -1,59 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.cbor.decoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborDecoderBase} from '../cbor/CborDecoderBase'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const encoder = new CborEncoder(); - -const encodedPayloads = payloads.map((payload) => { - return { - ...payload, - data: encoder.encode(payload.data), - }; -}); - -const benchmark: IBenchmark = { - name: 'CBOR Decoding', - warmup: 1000, - payloads: encodedPayloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoderBase(); - const json = decoder.read(payload as Buffer); - return deepEqual(json, data); - }, - runners: [ - { - name: 'json-joy/json-pack CborDecoder', - setup: () => { - const decoder = new CborDecoderBase(); - return (data: any) => decoder.read(data); - }, - }, - { - name: 'cbor-x', - setup: () => { - const {decode} = require('cbor-x'); - return (data: any) => decode(data); - }, - }, - { - name: 'cborg', - setup: () => { - const {decode} = require('cborg'); - return (json: any) => decode(json); - }, - }, - { - name: 'cbor', - setup: () => { - const {decode} = require('cbor'); - return (data: any) => decode(data); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.cbor.encoding.ts b/src/json-pack/__bench__/bench.cbor.encoding.ts deleted file mode 100644 index 2cca85b733..0000000000 --- a/src/json-pack/__bench__/bench.cbor.encoding.ts +++ /dev/null @@ -1,58 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.cbor.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborEncoderFast} from '../cbor/CborEncoderFast'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {deepEqual} from '../../json-equal/deepEqual'; -import {payloads} from '../../__bench__/payloads'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads: payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: 'json-joy/json-pack CborEncoderFast', - setup: () => { - const encoder = new CborEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack CborEncoder', - setup: () => { - const encoder = new CborEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'cbor-x', - setup: () => { - const {encode} = require('cbor-x'); - return (json: any) => encode(json); - }, - }, - { - name: 'cborg', - setup: () => { - const {encode} = require('cborg'); - return (json: any) => encode(json); - }, - }, - { - name: 'cbor', - setup: () => { - const {encode} = require('cbor'); - return (json: any) => encode(json); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.encoders.ts b/src/json-pack/__bench__/bench.encoders.ts deleted file mode 100644 index bd3417390d..0000000000 --- a/src/json-pack/__bench__/bench.encoders.ts +++ /dev/null @@ -1,84 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.encoders.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborEncoderFast} from '../cbor/CborEncoderFast'; -import {MsgPackEncoderFast} from '../msgpack/MsgPackEncoderFast'; -import {MsgPackEncoder} from '../msgpack/MsgPackEncoder'; -import {JsonEncoder} from '../json/JsonEncoder'; -import {UbjsonEncoder} from '../ubjson/UbjsonEncoder'; -import {IonEncoderFast} from '../ion/IonEncoderFast'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; -import {Writer} from '../../util/buffers/Writer'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: 'CborEncoderFast', - setup: () => { - const encoder = new CborEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'CborEncoder', - setup: () => { - const encoder = new CborEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'MsgPackEncoderFast', - setup: () => { - const encoder = new MsgPackEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'MsgPackEncoder', - setup: () => { - const encoder = new MsgPackEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'JsonEncoder', - setup: () => { - const encoder = new JsonEncoder(new Writer()); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'UbjsonEncoder', - setup: () => { - const encoder = new UbjsonEncoder(new Writer()); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'IonEncoderFast', - setup: () => { - const encoder = new IonEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'Buffer.from(JSON.stringify())', - setup: () => { - return (json: any) => Buffer.from(JSON.stringify(json)); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.encoding.cbor.ts b/src/json-pack/__bench__/bench.encoding.cbor.ts deleted file mode 100644 index aeb2900c54..0000000000 --- a/src/json-pack/__bench__/bench.encoding.cbor.ts +++ /dev/null @@ -1,77 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.encoding.cbor.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoderFast} from '../cbor/CborEncoderFast'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {payloads} from '../../__bench__/payloads'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - runners: [ - { - name: 'JSON.stringify()', - setup: () => { - return (json: any) => JSON.stringify(json); - }, - }, - { - name: 'Buffer.from(JSON.stringify())', - setup: () => { - return (json: any) => Buffer.from(JSON.stringify(json)); - }, - }, - { - name: 'json-joy/json-pack CborEncoderFast', - setup: () => { - const encoder = new CborEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack CborEncoder', - setup: () => { - const encoder = new CborEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'cbor-x', - setup: () => { - const {encode} = require('cbor-x'); - return (json: any) => encode(json); - }, - }, - // { - // name: 'cbor', - // setup: () => { - // const {encode} = require('cbor'); - // return (json: any) => encode(json); - // }, - // }, - { - name: 'cbor-js', - setup: () => { - const {encode} = require('cbor-js'); - return (json: any) => encode(json); - }, - }, - { - name: 'cborg', - setup: () => { - const {encode} = require('cborg'); - return (json: any) => encode(json); - }, - }, - { - name: 'cbor-sync', - setup: () => { - const {encode} = require('cbor-sync'); - return (json: any) => encode(json); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.encoding.ts b/src/json-pack/__bench__/bench.encoding.ts deleted file mode 100644 index b1f48a898f..0000000000 --- a/src/json-pack/__bench__/bench.encoding.ts +++ /dev/null @@ -1,139 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {JsonEncoder} from '../json/JsonEncoder'; -import {UbjsonEncoder} from '../ubjson/UbjsonEncoder'; -import {CborEncoderFast} from '../cbor/CborEncoderFast'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads} from '../../__bench__/payloads'; -import {MsgPackEncoderFast} from '../msgpack'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - runners: [ - { - name: 'json-joy/json-pack JsonEncoder', - setup: () => { - const writer = new Writer(); - const encoder = new JsonEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack UbjsonEncoder', - setup: () => { - const writer = new Writer(); - const encoder = new UbjsonEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '@shelacek/ubjson', - setup: () => { - const {encode} = require('@shelacek/ubjson'); - return (json: any) => encode(json); - }, - }, - { - name: 'Buffer.from(JSON.stringify())', - setup: () => { - return (json: any) => Buffer.from(JSON.stringify(json)); - }, - }, - { - name: 'json-joy/json-pack CborEncoderFast', - setup: () => { - const encoder = new CborEncoderFast(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack CborEncoder', - setup: () => { - const encoder = new CborEncoder(); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'json-joy/json-pack MsgPackEncoderFast', - setup: () => { - const encoder = new MsgPackEncoderFast(); - const jsonPack4 = encoder.encode.bind(encoder); - return (json: any) => jsonPack4(json); - }, - }, - { - name: 'JSON.stringify()', - setup: () => { - return (json: any) => JSON.stringify(json); - }, - }, - { - name: '@msgpack/msgpack', - setup: () => { - const {encode} = require('@msgpack/msgpack'); - return (json: any) => encode(json); - }, - }, - { - name: 'msgpackr', - setup: () => { - const {Packr} = require('msgpackr'); - const packr = new Packr(); - return (json: any) => packr.pack(json); - }, - }, - { - name: 'cbor-x', - setup: () => { - const {encode} = require('cbor-x'); - return (json: any) => encode(json); - }, - }, - // { - // name: 'ion-js', - // setup: () => { - // const {makeBinaryWriter, dom} = require('ion-js'); - // return (json: any) => { - // const writer = makeBinaryWriter(); - // dom.Value.from(json).writeTo(writer); - // writer.close(); - // return writer.getBytes(); - // }; - // }, - // }, - { - name: 'msgpack-lite', - setup: () => { - const {encode} = require('msgpack-lite'); - return (json: any) => encode(json); - }, - }, - { - name: 'msgpack5', - setup: () => { - const {encode} = require('msgpack5')(); - return (json: any) => encode(json); - }, - }, - // { - // name: 'cbor', - // setup: () => { - // const {encode} = require('cbor'); - // return (json: any) => encode(json); - // }, - // }, - { - name: 'messagepack', - setup: () => { - const {encode} = require('messagepack'); - return (json: any) => encode(json); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.ion.encoding.ts b/src/json-pack/__bench__/bench.ion.encoding.ts deleted file mode 100644 index b59d8b6c28..0000000000 --- a/src/json-pack/__bench__/bench.ion.encoding.ts +++ /dev/null @@ -1,48 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.ion.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {IonEncoderFast} from '../ion/IonEncoderFast'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads} from '../../__bench__/payloads'; -import {load, makeBinaryWriter, dom} from 'ion-js'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoded = load(data as any); - const json = JSON.parse(JSON.stringify(decoded)); - return deepEqual(payload, json); - }, - runners: [ - { - name: 'json-joy/json-pack IonEncoderFast', - setup: () => { - const writer = new Writer(); - const encoder = new IonEncoderFast(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'ion-js', - setup: () => { - return (json: any) => { - const writer = makeBinaryWriter(); - dom.Value.from(json).writeTo(writer); - writer.close(); - return writer.getBytes(); - }; - }, - }, - // { - // name: 'Buffer.from(JSON.stringify())', - // setup: () => { - // return (json: any) => Buffer.from(JSON.stringify(json)); - // }, - // }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.json.decoding.ts b/src/json-pack/__bench__/bench.json.decoding.ts deleted file mode 100644 index e9acf61e59..0000000000 --- a/src/json-pack/__bench__/bench.json.decoding.ts +++ /dev/null @@ -1,47 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.json.decoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {JsonDecoder} from '../json/JsonDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const encodedPayloads = payloads.map((payload) => { - return { - ...payload, - data: Buffer.from(JSON.stringify(payload.data)), - }; -}); - -const benchmark: IBenchmark = { - name: 'Decoding JSON', - warmup: 1000, - payloads: encodedPayloads, - test: (payload: unknown, data: unknown): boolean => { - const json = JSON.parse((payload as Buffer).toString()); - return deepEqual(json, data); - }, - runners: [ - { - name: 'json-joy/json-pack JsonDecoder.decode()', - setup: () => { - const decoder = new JsonDecoder(); - return (json: any) => decoder.read(json); - }, - }, - { - name: 'Native JSON.parse(buf.toString())', - setup: () => { - return (buf: any) => JSON.parse(buf.toString()); - }, - }, - { - name: 'sjson.parse()', - setup: () => { - const sjson = require('secure-json-parse'); - return (buf: any) => sjson.parse(buf.toString()); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.json.encoding.ts b/src/json-pack/__bench__/bench.json.encoding.ts deleted file mode 100644 index a046b4fc78..0000000000 --- a/src/json-pack/__bench__/bench.json.encoding.ts +++ /dev/null @@ -1,53 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.json.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {JsonEncoder} from '../json/JsonEncoder'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; -const safeStringify = require('fast-safe-stringify'); - -const benchmark: IBenchmark = { - name: 'Encoding JSON', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const buf = Buffer.from(data as Uint8Array | Buffer); - const json = JSON.parse(buf.toString()); - return deepEqual(payload, json); - }, - runners: [ - { - name: 'json-joy/json-pack JsonEncoder.encode()', - setup: () => { - const writer = new Writer(); - const encoder = new JsonEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'Native Buffer.from(JSON.stringify())', - setup: () => { - return (json: any) => Buffer.from(JSON.stringify(json)); - }, - }, - { - name: 'fast-safe-stringify Buffer.from(stringify())', - setup: () => { - return (json: any) => { - return Buffer.from(safeStringify(json)); - }; - }, - }, - { - name: 'fast-safe-stringify Buffer.from(stableStringify())', - setup: () => { - return (json: any) => { - return Buffer.from(safeStringify.stableStringify(json)); - }; - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.msgpack.decoding.ts b/src/json-pack/__bench__/bench.msgpack.decoding.ts deleted file mode 100644 index 3541724ad3..0000000000 --- a/src/json-pack/__bench__/bench.msgpack.decoding.ts +++ /dev/null @@ -1,82 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.msgpack.decoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {MsgPackEncoderFast} from '../msgpack/MsgPackEncoderFast'; -import {MsgPackDecoderFast} from '../msgpack/MsgPackDecoderFast'; -import {MsgPackDecoder} from '../msgpack/MsgPackDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const encoder = new MsgPackEncoderFast(); - -const encodedPayloads = payloads.map((payload) => { - return { - ...payload, - data: encoder.encode(payload.data), - }; -}); - -const benchmark: IBenchmark = { - name: 'MessagePack Decoding', - warmup: 1000, - payloads: encodedPayloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new MsgPackDecoderFast(); - const json = decoder.read(payload as Buffer); - return deepEqual(json, data); - }, - runners: [ - { - name: 'json-joy/json-pack MsgPackDecoderFast', - setup: () => { - const decoder = new MsgPackDecoderFast(); - return (data: any) => decoder.read(data); - }, - }, - { - name: 'json-joy/json-pack MsgPackDecoder', - setup: () => { - const decoder = new MsgPackDecoder(); - return (data: any) => decoder.read(data); - }, - }, - { - name: 'msgpackr', - setup: () => { - const {unpack} = require('msgpackr'); - return (data: any) => unpack(data); - }, - }, - { - name: '@msgpack/msgpack', - setup: () => { - const {Decoder} = require('@msgpack/msgpack'); - const decoder = new Decoder(); - return (data: any) => decoder.decode(data); - }, - }, - { - name: 'msgpack-lite', - setup: () => { - const {decode} = require('msgpack-lite'); - return (data: any) => decode(data); - }, - }, - { - name: 'msgpack5', - setup: () => { - const {decode} = require('msgpack5')(); - return (data: any) => decode(data); - }, - }, - { - name: 'messagepack', - setup: () => { - const {decode} = require('messagepack'); - return (data: any) => decode(data); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.msgpack.encoding.ts b/src/json-pack/__bench__/bench.msgpack.encoding.ts deleted file mode 100644 index c4b74e9bd6..0000000000 --- a/src/json-pack/__bench__/bench.msgpack.encoding.ts +++ /dev/null @@ -1,73 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.msgpack.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {MsgPackEncoder} from '../msgpack/MsgPackEncoder'; -import {MsgPackEncoderFast} from '../msgpack/MsgPackEncoderFast'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const benchmark: IBenchmark = { - name: 'MessagePack Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: 'json-joy/json-pack MsgPackEncoderFast', - setup: () => { - const encoder = new MsgPackEncoderFast(); - return (data: any) => encoder.encode(data); - }, - }, - { - name: 'json-joy/json-pack MsgPackEncoder', - setup: () => { - const encoder = new MsgPackEncoder(); - return (data: any) => encoder.encode(data); - }, - }, - { - name: 'msgpackr', - setup: () => { - const {pack} = require('msgpackr'); - return (data: any) => pack(data); - }, - }, - { - name: '@msgpack/msgpack', - setup: () => { - const {Encoder} = require('@msgpack/msgpack'); - const encoder = new Encoder(); - return (data: any) => encoder.encode(data); - }, - }, - { - name: 'msgpack-lite', - setup: () => { - const {encode} = require('msgpack-lite'); - return (data: any) => encode(data); - }, - }, - { - name: 'msgpack5', - setup: () => { - const {encode} = require('msgpack5')(); - return (data: any) => encode(data); - }, - }, - { - name: 'messagepack', - setup: () => { - const {encode} = require('messagepack'); - return (data: any) => encode(data); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.resp.decoding.ts b/src/json-pack/__bench__/bench.resp.decoding.ts deleted file mode 100644 index 4725765732..0000000000 --- a/src/json-pack/__bench__/bench.resp.decoding.ts +++ /dev/null @@ -1,70 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.resp.decoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {RespEncoder} from '../resp/RespEncoder'; -import {RespDecoder} from '../resp/RespDecoder'; -import {RespStreamingDecoder} from '../resp/RespStreamingDecoder'; - -const encoder = new RespEncoder(); -const data = encoder.encode(['set', 'production:project-name:keys:foobarbaz', 'PX', 'NX', 'EX', 60000, 'KEEPTTL']); - -const benchmark: IBenchmark = { - name: 'Decoding RESP', - warmup: 1000, - payloads: [ - { - name: 'short array', - data, - }, - ], - runners: [ - { - name: 'json-joy/json-pack RespDecoder', - setup: () => { - const decoder = new RespDecoder(); - return (data: any) => { - decoder.read(data); - }; - }, - }, - { - name: 'json-joy/json-pack RespStreamingDecoder', - setup: () => { - const decoder = new RespStreamingDecoder(); - return (data: any) => { - decoder.push(data); - decoder.read(); - }; - }, - }, - { - name: 'redis-parser', - setup: () => { - const Parser = require('redis-parser'); - let result: unknown; - const parser = new Parser({ - returnReply(reply: any, b: any, c: any) { - result = reply; - }, - returnError(err: any) { - result = err; - }, - returnFatalError(err: any) { - result = err; - }, - returnBuffers: false, - stringNumbers: false, - }); - const parse = (uint8: Uint8Array): unknown => { - parser.execute(Buffer.from(uint8)); - return result; - }; - return (data: any) => { - parse(data); - }; - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.resp.encoding.ts b/src/json-pack/__bench__/bench.resp.encoding.ts deleted file mode 100644 index 199c2cb5fb..0000000000 --- a/src/json-pack/__bench__/bench.resp.encoding.ts +++ /dev/null @@ -1,52 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.resp.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {RespEncoder} from '../resp/RespEncoder'; -import encodeCommand from '@redis/client/dist/lib/client/RESP2/encoder'; - -const data = ['set', 'production:project-name:keys:foobarbaz', 'PX', 'NX', 'EX', '60000', 'KEEPTTL']; -const redisClientEncode = (cmd: string[]) => { - const list = encodeCommand(data); - return Buffer.from(list.join('')); -}; - -const benchmark: IBenchmark = { - name: 'Encoding RESP', - warmup: 1000, - payloads: [ - { - name: 'short array', - data, - }, - ], - runners: [ - { - name: 'json-joy/json-pack RespEncoder.encode()', - setup: () => { - const encoder = new RespEncoder(); - return (data: any) => { - encoder.encode(data); - }; - }, - }, - { - name: 'json-joy/json-pack RespEncoder.encodeCmd()', - setup: () => { - const encoder = new RespEncoder(); - return (data: any) => { - encoder.encodeCmd(data); - }; - }, - }, - { - name: '@redis/client', - setup: () => { - return (data: any) => { - redisClientEncode(data); - }; - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.shallow-read.ts b/src/json-pack/__bench__/bench.shallow-read.ts deleted file mode 100644 index a46959003d..0000000000 --- a/src/json-pack/__bench__/bench.shallow-read.ts +++ /dev/null @@ -1,118 +0,0 @@ -import {runBenchmark} from '../../__bench__/runBenchmark'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {MsgPackEncoderFast} from '../msgpack'; -import {MsgPackDecoder} from '../msgpack/MsgPackDecoder'; -import {genShallowReader} from '../msgpack/shallow-read'; - -const benchmark = { - name: 'Encoding', - warmup: 10000, - payloads: [ - { - name: (json: any) => `Typical object, ${JSON.stringify(json).length} bytes`, - data: require('../../__bench__/data/json2'), - test: () => 'Sports 🏀', - }, - ], - runners: [ - { - name: 'JSON.parse()', - setup: (json: any) => { - const doc = JSON.stringify(json); - return () => { - const parsed = JSON.parse(doc); - return parsed[5]?.value?.json?.tags[1]; - }; - }, - }, - { - name: 'msgpackr', - setup: (json: any) => { - const {decode} = require('msgpackr'); - const encoder = new MsgPackEncoderFast(); - const doc = encoder.encode(json); - return () => { - const parsed = decode(doc); - return parsed[5]?.value?.json?.tags[1]; - }; - }, - }, - { - name: 'cbor-x', - setup: (json: any) => { - const {decode} = require('cbor-x'); - const encoder = new CborEncoder(); - const doc = encoder.encode(json); - return () => { - const parsed = decode(doc); - return parsed[5]?.value?.json?.tags[1]; - }; - }, - }, - { - name: 'MsgPackDecoder', - setup: (json: any) => { - const encoder = new MsgPackEncoderFast(); - const doc = encoder.encode(json); - const decoder = new MsgPackDecoder(); - return () => { - const parsed = decoder.decode(doc) as any; - return parsed[5]?.value?.json?.tags[1]; - }; - }, - }, - { - name: 'CborDecoder', - setup: (json: any) => { - const encoder = new CborEncoder(); - const doc = encoder.encode(json); - const decoder = new CborDecoder(); - return () => { - const parsed = decoder.decode(doc) as any; - return parsed[5]?.value?.json?.tags[1]; - }; - }, - }, - { - name: 'MsgPackDecoder.{findKey,findIndex}()', - setup: (json: any) => { - const encoder = new MsgPackEncoderFast(); - const doc = encoder.encode(json); - const decoder = new MsgPackDecoder(); - return () => { - decoder.reader.reset(doc); - return decoder.findIndex(5).findKey('value').findKey('json').findKey('tags').findIndex(1).val(); - }; - }, - }, - { - name: 'MsgPackDecoder.find()', - setup: (json: any) => { - const encoder = new MsgPackEncoderFast(); - const doc = encoder.encode(json); - const decoder = new MsgPackDecoder(); - return () => { - decoder.reader.reset(doc); - return decoder.find([5, 'value', 'json', 'tags', 1]).val(); - }; - }, - }, - { - name: 'genShallowReader()(MsgPackDecoder)', - setup: (json: any) => { - const encoder = new MsgPackEncoderFast(); - const doc = encoder.encode(json); - const fn = genShallowReader([5, 'value', 'json', 'tags', 1]); - const decoder = new MsgPackDecoder(); - return () => { - decoder.reader.reset(doc); - fn(decoder); - return decoder.val(); - }; - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.slice.ts b/src/json-pack/__bench__/bench.slice.ts deleted file mode 100644 index b837f5e77d..0000000000 --- a/src/json-pack/__bench__/bench.slice.ts +++ /dev/null @@ -1,36 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.slice.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const encoder = new CborEncoder(); - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: 'Uint8Array', - setup: () => { - return (json: any) => encoder.encode(json); - }, - }, - { - name: 'Slice', - setup: () => { - return (json: any) => encoder.encodeToSlice(json); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.ubjson.decoding.ts b/src/json-pack/__bench__/bench.ubjson.decoding.ts deleted file mode 100644 index d1f7cd4942..0000000000 --- a/src/json-pack/__bench__/bench.ubjson.decoding.ts +++ /dev/null @@ -1,44 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.ubjson.decoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {UbjsonEncoder} from '../ubjson/UbjsonEncoder'; -import {UbjsonDecoder} from '../ubjson/UbjsonDecoder'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; - -const encoder = new UbjsonEncoder(new Writer()); -const encodedPayloads = payloads.map((payload) => { - return { - ...payload, - data: encoder.encode(payload.data), - }; -}); - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads: encodedPayloads, - test: (payload: unknown, data: unknown): boolean => { - const encoded = encoder.encode(data); - return deepEqual(encoded, payload); - }, - runners: [ - { - name: 'json-joy/json-pack UbjsonDecoder', - setup: () => { - const decoder = new UbjsonDecoder(); - return (data: any) => decoder.read(data); - }, - }, - { - name: '@shelacek/ubjson', - setup: () => { - const {decode} = require('@shelacek/ubjson'); - return (data: any) => decode(data); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.ubjson.encoding.ts b/src/json-pack/__bench__/bench.ubjson.encoding.ts deleted file mode 100644 index 7724613379..0000000000 --- a/src/json-pack/__bench__/bench.ubjson.encoding.ts +++ /dev/null @@ -1,37 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.ubjson.encoding.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {UbjsonEncoder} from '../ubjson/UbjsonEncoder'; -import {Writer} from '../../util/buffers/Writer'; -import {payloads} from '../../__bench__/payloads'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - runners: [ - { - name: 'json-joy/json-pack UbjsonEncoder', - setup: () => { - const writer = new Writer(); - const encoder = new UbjsonEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '@shelacek/ubjson', - setup: () => { - const {encode} = require('@shelacek/ubjson'); - return (json: any) => encode(json); - }, - }, - // { - // name: 'Buffer.from(JSON.stringify())', - // setup: () => { - // return (json: any) => Buffer.from(JSON.stringify(json)); - // }, - // }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/bench.writer-size.ts b/src/json-pack/__bench__/bench.writer-size.ts deleted file mode 100644 index f8f249cb51..0000000000 --- a/src/json-pack/__bench__/bench.writer-size.ts +++ /dev/null @@ -1,71 +0,0 @@ -// npx ts-node src/json-pack/__bench__/bench.writer-size.ts - -import {runBenchmark, IBenchmark} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {payloads} from '../../__bench__/payloads'; -import {deepEqual} from '../../json-equal/deepEqual'; -import {Writer} from '../../util/buffers/Writer'; - -const benchmark: IBenchmark = { - name: 'Encoding', - warmup: 1000, - payloads, - test: (payload: unknown, data: unknown): boolean => { - const decoder = new CborDecoder(); - const decoded = decoder.read(data as any); - return deepEqual(decoded, payload); - }, - runners: [ - { - name: '1 MB', - setup: () => { - const writer = new Writer(1024 * 256 * 4); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '256 KB', - setup: () => { - const writer = new Writer(1024 * 256); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '64 KB', - setup: () => { - const writer = new Writer(1024 * 64); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '16 KB', - setup: () => { - const writer = new Writer(1024 * 16); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '4 KB', - setup: () => { - const writer = new Writer(1024 * 4); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - { - name: '1 KB', - setup: () => { - const writer = new Writer(1024); - const encoder = new CborEncoder(writer); - return (json: any) => encoder.encode(json); - }, - }, - ], -}; - -runBenchmark(benchmark); diff --git a/src/json-pack/__bench__/profiler/cbor-decoding.ts b/src/json-pack/__bench__/profiler/cbor-decoding.ts deleted file mode 100644 index ac8e3fe2cd..0000000000 --- a/src/json-pack/__bench__/profiler/cbor-decoding.ts +++ /dev/null @@ -1,20 +0,0 @@ -// NODE_ENV=production node --prof -r ts-node/register src/json-pack/__bench__/profiler/cbor-decoding.ts -// node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt - -import {CborEncoder} from '../../cbor/CborEncoder'; -import {CborDecoder} from '../../cbor/CborDecoder'; - -const payload = [ - 0, 1, 2, 333, -333, 44444, -55555, 556666, -6666666, 62343423432, 0.123, 0.0, -123.3434343, 127, 128, 129, 255, 256, - 257, 258, 1000, 1000, 1000, -222222, -22222, 0xff, 0xfe, 0x100, 0x101, - // 0xffff, 0xfffe, 0x10000, -0x7f, -0x80, -0x81, -0x100, -0x101, -0x10000, - // 0xffffffff, 0xfffffffe, 0x100000000, 0x100000001, 0xffffffffffffffff, - // 0xfffffffffffffffe, 0x10000000000000000, 0x10000000000000001, - // 0x100000000000000000, 0x100000000000000001, 0x1000000000000000000, -]; -const encoded = new CborEncoder().encode(payload); -const decoder = new CborDecoder(); - -for (let i = 0; i < 10e6; i++) { - decoder.read(encoded); -} diff --git a/src/json-pack/__bench__/profiler/slices.ts b/src/json-pack/__bench__/profiler/slices.ts deleted file mode 100644 index 32c8881ecd..0000000000 --- a/src/json-pack/__bench__/profiler/slices.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* tslint:disable no-console */ - -const iterations = 10000000; -const buf = new ArrayBuffer(1024 * 4); -const arr = new Uint8Array(buf); -const arr2 = Buffer.from(buf); -const arr3 = Buffer.allocUnsafe(1024 * 4); -const FastBuffer = (Buffer as any)[Symbol.species] as any; - -class Slice { - constructor( - public uint8: ArrayBuffer, - public start: number, - public end: number, - ) {} -} - -const res = { - end: (() => {}) as any, -}; - -console.time('res.end(buf, offset, length)'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(buf, pos, pos + 1); -} -console.timeEnd('res.end(buf, offset, length)'); - -console.time('new Slice()'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(new Slice(buf, pos, pos + 1)); -} -console.timeEnd('new Slice()'); - -console.time('new FastBuffer()'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(new FastBuffer(buf, pos, 1)); -} -console.timeEnd('new FastBuffer()'); - -console.time('new Uint8Array()'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(new Uint8Array(buf, pos, 1)); -} -console.timeEnd('new Uint8Array()'); - -console.time('Uint8Array.prototype.subarray()'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(arr.subarray(pos, pos + 1)); -} -console.timeEnd('Uint8Array.prototype.subarray()'); - -console.time('Buffer.prototype.subarray()'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(arr2.subarray(pos, pos + 1)); -} -console.timeEnd('Buffer.prototype.subarray()'); - -console.time('Buffer.prototype.subarray() - 2'); -for (let i = 0; i < iterations; i++) { - const pos = i % 1024; - res.end(arr3.subarray(pos, pos + 1)); -} -console.timeEnd('Buffer.prototype.subarray() - 2'); diff --git a/src/json-pack/__bench__/profiler/time.ts b/src/json-pack/__bench__/profiler/time.ts deleted file mode 100644 index 563ac5bc21..0000000000 --- a/src/json-pack/__bench__/profiler/time.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* tslint:disable no-console */ - -import {MsgPackEncoderFast} from '../../msgpack/MsgPackEncoderFast'; -import {Writer} from '../../../util/buffers/Writer'; - -const json = [1234]; - -const writer = new Writer(); -const encoder = new MsgPackEncoderFast(); - -const arr = new ArrayBuffer(1024 * 4); -const uint8 = new Uint8Array(arr); -const buf = Buffer.alloc(1024 * 4); - -console.time('loop'); -for (let i = 0; i < 10000000; i++) { - writer.utf8('asdf'); - writer.u8(123); - // writer.u8u32(123, 123123); - writer.reset(); - // writer.flush(); - // arr.slice(i % 1024, i % 1024 + 1); - // buf.slice(i % 1024, i % 1024 + 1); - // (buf as any).hexSlice(i % 1024, i % 1024 + 1); - // const pos = i % 1024; - // new Slice(uint8, pos, pos + 1); - // uint8.subarray(pos, pos + 1); - // new Uint8Array(arr.buffer, arr.byteOffset + pos, 1); - // arr.slice(pos, pos + 1); -} -console.timeEnd('loop'); diff --git a/src/json-pack/__bench__/profiler/truncate.ts b/src/json-pack/__bench__/profiler/truncate.ts deleted file mode 100644 index 8c8b0e9e3f..0000000000 --- a/src/json-pack/__bench__/profiler/truncate.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* tslint:disable no-console */ - -const i = 10000; -class MySlice { - constructor( - public uint8: ArrayBuffer, - public start: number, - public end: number, - ) {} -} - -console.time('new Slice()'); -for (let i = 0; i < iterations; i++) { - const buf = new ArrayBuffer(1024 * 4); - for (let j = 1024; j > 0; j--) { - new Slice(buf, 0, j); - } -} -console.timeEnd('new Slice()'); - -console.time('new Uint8Array()'); -for (let i = 0; i < iterations; i++) { - const buf = new ArrayBuffer(1024 * 4); - for (let j = 1024; j > 0; j--) { - new Uint8Array(buf, 0, j); - } -} -console.timeEnd('new Uint8Array()'); - -console.time('ArrayBuffer.prototype.resize'); -for (let i = 0; i < iterations; i++) { - const buf = new (ArrayBuffer as any)(1024 * 4, {maxByteLength: 1024 * 4}); - for (let j = 1024; j > 0; j--) { - buf.resize(j); - } -} -console.timeEnd('ArrayBuffer.prototype.resize'); diff --git a/src/json-pack/__demos__/cbor.ts b/src/json-pack/__demos__/cbor.ts deleted file mode 100644 index f7e44e7184..0000000000 --- a/src/json-pack/__demos__/cbor.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* tslint:disable no-console */ - -/** - * Run this demo with: - * - * npx nodemon -q -x npx ts-node src/json-pack/__demos__/cbor.ts - */ - -import {CborEncoder} from '../cbor/CborEncoder'; -import {CborDecoder} from '../cbor/CborDecoder'; -import {CborDecoderBase} from '../cbor/CborDecoderBase'; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); -const decoderBase = new CborDecoderBase(); - -const pojo = { - id: 123, - foo: 'bar', - tags: ['a', 'b', 'c'], - nested: { - a: 1, - b: 2, - level2: { - c: 3, - }, - }, -}; - -console.clear(); - -console.log('--------------------------------------------------'); -console.log('Encoding CBOR:'); -const encoded = encoder.encode(pojo); -console.log(encoded); - -console.log('--------------------------------------------------'); -console.log('Decoding CBOR:'); -const decoded = decoderBase.read(encoded); -console.log(decoded); - -console.log('--------------------------------------------------'); -console.log('Retrieving values without parsing:'); -decoder.reader.reset(encoded); -const id = decoder.find(['id']).val(); -decoder.reader.reset(encoded); -const foo = decoder.find(['foo']).val(); -decoder.reader.reset(encoded); -const secondTag = decoder.find(['tags', 1]).val(); -decoder.reader.reset(encoded); -const nested = decoder.find(['nested', 'level2', 'c']).val(); -console.log('id:', id, 'foo:', foo, 'secondTag:', secondTag, 'nested:', nested); - -console.log('--------------------------------------------------'); -console.log('Asserting by value type:'); -decoder.reader.reset(encoded); -const tagAsString = decoder.find(['tags', 1]).readPrimitiveOrVal(); -console.log({tagAsString}); - -console.log('--------------------------------------------------'); -console.log('Parsing only one level:'); -const decodedLevel = decoder.decodeLevel(encoded); -console.log(decodedLevel); diff --git a/src/json-pack/__demos__/json.ts b/src/json-pack/__demos__/json.ts deleted file mode 100644 index 44c4c63914..0000000000 --- a/src/json-pack/__demos__/json.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* tslint:disable no-console */ - -/** - * Run this demo with: - * - * npx nodemon -q -x npx ts-node src/json-pack/__demos__/json.ts - */ - -import {JsonEncoder} from '../json/JsonEncoder'; -import {JsonDecoder} from '../json/JsonDecoder'; -import {Writer} from '../../util/buffers/Writer'; - -const encoder = new JsonEncoder(new Writer()); -const decoder = new JsonDecoder(); - -const pojo = { - id: 123, - foo: 'bar', - tags: ['a', 'b', 'c'], - binary: new Uint8Array([1, 2, 3]), -}; - -console.clear(); - -console.log('--------------------------------------------------'); -console.log('Encoding JSON:'); -const encoded = encoder.encode(pojo); -console.log(encoded); - -console.log('--------------------------------------------------'); -console.log('Decoding JSON:'); -const decoded = decoder.read(encoded); -console.log(decoded); - -console.log('--------------------------------------------------'); -console.log('Binary data:'); -const blob = encoder.encode({binary: new Uint8Array([1, 2, 3])}); -console.log(Buffer.from(blob).toString()); diff --git a/src/json-pack/__demos__/msgpack.ts b/src/json-pack/__demos__/msgpack.ts deleted file mode 100644 index 552a932887..0000000000 --- a/src/json-pack/__demos__/msgpack.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* tslint:disable no-console */ - -/** - * Run this demo with: - * - * npx nodemon -q -x npx ts-node src/json-pack/__demos__/msgpack.ts - */ - -import {MsgPackEncoder} from '../msgpack/MsgPackEncoder'; -import {MsgPackDecoder} from '../msgpack/MsgPackDecoder'; - -const encoder = new MsgPackEncoder(); -const decoder = new MsgPackDecoder(); - -const pojo = { - id: 123, - foo: 'bar', - tags: ['a', 'b', 'c'], - nested: { - a: 1, - b: 2, - level2: { - c: 3, - }, - }, -}; - -console.clear(); - -console.log('--------------------------------------------------'); -console.log('Encoding MessagePack:'); -const encoded = encoder.encode(pojo); -console.log(encoded); - -console.log('--------------------------------------------------'); -console.log('Retrieving values without parsing:'); -decoder.reader.reset(encoded); -const id = decoder.find(['id']).val(); -decoder.reader.reset(encoded); -const foo = decoder.find(['foo']).val(); -decoder.reader.reset(encoded); -const secondTag = decoder.find(['tags', 1]).val(); -decoder.reader.reset(encoded); -const nested = decoder.find(['nested', 'level2', 'c']).val(); -console.log('id:', id, 'foo:', foo, 'secondTag:', secondTag, 'nested:', nested); diff --git a/src/json-pack/__demos__/ubjson.ts b/src/json-pack/__demos__/ubjson.ts deleted file mode 100644 index 4f1dfa70a7..0000000000 --- a/src/json-pack/__demos__/ubjson.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* tslint:disable no-console */ - -/** - * Run this demo with: - * - * npx nodemon -q -x npx ts-node src/json-pack/__demos__/ubjson.ts - */ - -import {UbjsonEncoder} from '../ubjson/UbjsonEncoder'; -import {UbjsonDecoder} from '../ubjson/UbjsonDecoder'; -import {Writer} from '../../util/buffers/Writer'; - -const encoder = new UbjsonEncoder(new Writer()); -const decoder = new UbjsonDecoder(); - -const pojo = { - id: 123, - foo: 'bar', - tags: ['a', 'b', 'c'], - binary: new Uint8Array([1, 2, 3]), -}; - -console.clear(); - -console.log('--------------------------------------------------'); -console.log('Encoding UBJSON:'); -const encoded = encoder.encode(pojo); -console.log(encoded); - -console.log('--------------------------------------------------'); -console.log('Decoding UBJSON:'); -const decoded = decoder.read(encoded); -console.log(decoded); - -console.log('--------------------------------------------------'); -console.log('Binary data:'); -const blob = encoder.encode({binary: new Uint8Array([1, 2, 3])}); -console.log(Buffer.from(blob).toString()); diff --git a/src/json-pack/bencode/BencodeDecoder.ts b/src/json-pack/bencode/BencodeDecoder.ts deleted file mode 100644 index ecfb352698..0000000000 --- a/src/json-pack/bencode/BencodeDecoder.ts +++ /dev/null @@ -1,151 +0,0 @@ -import {Reader} from '../../util/buffers/Reader'; -import type {BinaryJsonDecoder, PackValue} from '../types'; - -export class BencodeDecoder implements BinaryJsonDecoder { - public reader = new Reader(); - - public read(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.readAny(); - } - - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.readAny(); - } - - public readAny(): unknown { - const reader = this.reader; - const x = reader.x; - const uint8 = reader.uint8; - const char = uint8[x]; - switch (char) { - case 0x69: // i - return this.readNum(); - case 0x64: // d - return this.readObj(); - case 0x6c: // l - return this.readArr(); - case 0x66: // f - return this.readFalse(); - case 0x74: // t - return this.readTrue(); - case 110: // n - return this.readNull(); - case 117: // u - return this.readUndef(); - default: - if (char >= 48 && char <= 57) return this.readBin(); - } - throw new Error('INVALID_BENCODE'); - } - - public readNull(): null { - if (this.reader.u8() !== 0x6e) throw new Error('INVALID_BENCODE'); - return null; - } - - public readUndef(): undefined { - if (this.reader.u8() !== 117) throw new Error('INVALID_BENCODE'); - return undefined; - } - - public readTrue(): true { - if (this.reader.u8() !== 0x74) throw new Error('INVALID_BENCODE'); - return true; - } - - public readFalse(): false { - if (this.reader.u8() !== 0x66) throw new Error('INVALID_BENCODE'); - return false; - } - - public readBool(): unknown { - const reader = this.reader; - switch (reader.uint8[reader.x]) { - case 0x66: // f - return this.readFalse(); - case 0x74: // t - return this.readTrue(); - default: - throw new Error('INVALID_BENCODE'); - } - } - - public readNum(): number { - const reader = this.reader; - const startChar = reader.u8(); - if (startChar !== 0x69) throw new Error('INVALID_BENCODE'); - const u8 = reader.uint8; - let x = reader.x; - let numStr = ''; - let c = u8[x++]; - let i = 0; - while (c !== 0x65) { - numStr += String.fromCharCode(c); - c = u8[x++]; - if (i > 25) throw new Error('INVALID_BENCODE'); - i++; - } - if (!numStr) throw new Error('INVALID_BENCODE'); - reader.x = x; - return +numStr; - } - - public readStr(): string { - const bin = this.readBin(); - return new TextDecoder().decode(bin); - } - - public readBin(): Uint8Array { - const reader = this.reader; - const u8 = reader.uint8; - let lenStr = ''; - let x = reader.x; - let c = u8[x++]; - let i = 0; - while (c !== 0x3a) { - if (c < 48 || c > 57) throw new Error('INVALID_BENCODE'); - lenStr += String.fromCharCode(c); - c = u8[x++]; - if (i > 10) throw new Error('INVALID_BENCODE'); - i++; - } - reader.x = x; - const len = +lenStr; - const bin = reader.buf(len); - return bin; - } - - public readArr(): unknown[] { - const reader = this.reader; - if (reader.u8() !== 0x6c) throw new Error('INVALID_BENCODE'); - const arr: unknown[] = []; - const uint8 = reader.uint8; - while (true) { - const char = uint8[reader.x]; - if (char === 0x65) { - reader.x++; - return arr; - } - arr.push(this.readAny()); - } - } - - public readObj(): PackValue | Record | unknown { - const reader = this.reader; - if (reader.u8() !== 0x64) throw new Error('INVALID_BENCODE'); - const obj: Record = {}; - const uint8 = reader.uint8; - while (true) { - const char = uint8[reader.x]; - if (char === 0x65) { - reader.x++; - return obj; - } - const key = this.readStr(); - if (key === '__proto__') throw new Error('INVALID_KEY'); - obj[key] = this.readAny(); - } - } -} diff --git a/src/json-pack/bencode/BencodeEncoder.ts b/src/json-pack/bencode/BencodeEncoder.ts deleted file mode 100644 index 61ff9b76d9..0000000000 --- a/src/json-pack/bencode/BencodeEncoder.ts +++ /dev/null @@ -1,164 +0,0 @@ -import {utf8Size} from '../../util/strings/utf8'; -import {sort} from '../../util/sort/insertion'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder} from '../types'; - -export class BencodeEncoder implements BinaryJsonEncoder { - constructor(public readonly writer: IWriter & IWriterGrowable) {} - - public encode(value: unknown): Uint8Array { - const writer = this.writer; - writer.reset(); - this.writeAny(value); - return writer.flush(); - } - - /** - * Called when the encoder encounters a value that it does not know how to encode. - * - * @param value Some JavaScript value. - */ - public writeUnknown(value: unknown): void { - this.writeNull(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'boolean': - return this.writeBoolean(value); - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'object': { - if (value === null) return this.writeNull(); - const constructor = value.constructor; - switch (constructor) { - case Object: - return this.writeObj(value as Record); - case Array: - return this.writeArr(value as unknown[]); - case Uint8Array: - return this.writeBin(value as Uint8Array); - case Map: - return this.writeMap(value as Map); - case Set: - return this.writeSet(value as Set); - default: - return this.writeUnknown(value); - } - } - case 'bigint': { - return this.writeBigint(value); - } - case 'undefined': { - return this.writeUndef(); - } - default: - return this.writeUnknown(value); - } - } - - public writeNull(): void { - this.writer.u8(110); // 'n' - } - - public writeUndef(): void { - this.writer.u8(117); // 'u' - } - - public writeBoolean(bool: boolean): void { - this.writer.u8(bool ? 0x74 : 0x66); // 't' or 'f' - } - - public writeNumber(num: number): void { - const writer = this.writer; - writer.u8(0x69); // 'i' - writer.ascii(Math.round(num) + ''); - writer.u8(0x65); // 'e' - } - - public writeInteger(int: number): void { - const writer = this.writer; - writer.u8(0x69); // 'i' - writer.ascii(int + ''); - writer.u8(0x65); // 'e' - } - - public writeUInteger(uint: number): void { - this.writeInteger(uint); - } - - public writeFloat(float: number): void { - this.writeNumber(float); - } - - public writeBigint(int: bigint): void { - const writer = this.writer; - writer.u8(0x69); // 'i' - writer.ascii(int + ''); - writer.u8(0x65); // 'e' - } - - public writeBin(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.ascii(length + ''); - writer.u8(0x3a); // ':' - writer.buf(buf, length); - } - - public writeStr(str: string): void { - const writer = this.writer; - const length = utf8Size(str); - writer.ascii(length + ''); - writer.u8(0x3a); // ':' - writer.ensureCapacity(length); - writer.utf8(str); - } - - public writeAsciiStr(str: string): void { - const writer = this.writer; - writer.ascii(str.length + ''); - writer.u8(0x3a); // ':' - writer.ascii(str); - } - - public writeArr(arr: unknown[]): void { - const writer = this.writer; - writer.u8(0x6c); // 'l' - const length = arr.length; - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - writer.u8(0x65); // 'e' - } - - public writeObj(obj: Record): void { - const writer = this.writer; - writer.u8(0x64); // 'd' - const keys = sort(Object.keys(obj)); - const length = keys.length; - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - writer.u8(0x65); // 'e' - } - - public writeMap(obj: Map): void { - const writer = this.writer; - writer.u8(0x64); // 'd' - const keys = sort([...obj.keys()]); - const length = keys.length; - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key + ''); - this.writeAny(obj.get(key)); - } - writer.u8(0x65); // 'e' - } - - public writeSet(set: Set): void { - this.writeArr([...set.values()]); - } -} diff --git a/src/json-pack/bencode/README.md b/src/json-pack/bencode/README.md deleted file mode 100644 index 011fb12013..0000000000 --- a/src/json-pack/bencode/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Bencode codecs - -Implements [Bencode][bencode] encoder and decoder. - -[bencode]: https://en.wikipedia.org/wiki/Bencode - -Type coercion: - -- Strings and `Uint8Array` are encoded as Bencode byte strings, decoded as `Uint8Array`. -- `Object` and `Map` are encoded as Bencode dictionaries, decoded as `Object`. -- `Array` and `Set` are encoded as Bencode lists, decoded as `Array`. -- `number` and `bigint` are encoded as Bencode integers, decoded as `number`. -- Float `number` are rounded and encoded as Bencode integers, decoded as `number`. - - -## Extensions - -This codec extends the Bencode specification to support the following types: - -- `null` (encoded as `n`) -- `undefined` (encoded as `u`) -- `boolean` (encoded as `t` for `true` and `f` for `false`) diff --git a/src/json-pack/bencode/__tests__/BencodeDecoder.spec.ts b/src/json-pack/bencode/__tests__/BencodeDecoder.spec.ts deleted file mode 100644 index 122f1e3d7e..0000000000 --- a/src/json-pack/bencode/__tests__/BencodeDecoder.spec.ts +++ /dev/null @@ -1,271 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {BencodeEncoder} from '../BencodeEncoder'; -import {BencodeDecoder} from '../BencodeDecoder'; -import {utf8} from '../../../util/buffers/strings'; - -const decoder = new BencodeDecoder(); - -describe('null', () => { - test('null', () => { - const data = utf8`n`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(null); - }); -}); - -describe('undefined', () => { - test('undefined', () => { - const encoder = new BencodeEncoder(new Writer()); - const encoded = encoder.encode(undefined); - const decoded = decoder.read(encoded); - expect(decoded).toBe(undefined); - }); - - test('undefined in array', () => { - const encoder = new BencodeEncoder(new Writer()); - const encoded = encoder.encode({foo: [1, undefined, -1]}); - const decoded = decoder.read(encoded); - expect(decoded).toEqual({foo: [1, undefined, -1]}); - }); -}); - -describe('boolean', () => { - test('true', () => { - const data = utf8`t`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(true); - }); - - test('false', () => { - const data = utf8`f`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(false); - }); -}); - -describe('number', () => { - test('1', () => { - const data = utf8`i1e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(1); - }); - - test('12', () => { - const data = utf8`i12e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(12); - }); - - test('123', () => { - const data = utf8`i123e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(123); - }); - - test('1234', () => { - const data = utf8`i1234e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(1234); - }); - - test('12345', () => { - const data = utf8`i12345e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(12345); - }); - - test('123456', () => { - const data = utf8`i123456e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(123456); - }); - - test('-0.1234', () => { - const data = utf8`i-123e`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(-123); - }); -}); - -describe('string', () => { - test('empty string', () => { - const data = utf8`0:`; - const value = decoder.decode(data); - expect(value).toEqual(utf8``); - }); - - test('one char string', () => { - const data = utf8`1:a`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8`a`); - }); - - test('"hello world" string', () => { - const data = utf8`11:hello world`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8`hello world`); - }); - - test('string with emoji', () => { - const str = 'yes! - 👍🏻👍🏼👍🏽👍🏾👍🏿'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('string with quote', () => { - const str = 'this is a "quote"'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('string with new line', () => { - const str = 'this is a \n new line'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('string with backslash', () => { - const str = 'this is a \\ backslash'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('a single backslash character', () => { - const str = '\\'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('string with tab', () => { - const str = 'this is a \t tab'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); - - test('string unicode characters', () => { - const str = '15\u00f8C'; - const buf = Buffer.from(str, 'utf-8'); - const data = utf8(`${buf.length}:${str}`); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(utf8(str)); - }); -}); - -describe('binary', () => { - test('empty buffer', () => { - const encoder = new BencodeEncoder(new Writer()); - const data = encoder.encode(new Uint8Array(0)); - decoder.reader.reset(data); - const value1 = decoder.readAny(); - expect(value1).toEqual(new Uint8Array(0)); - decoder.reader.reset(data); - const value2 = decoder.readBin(); - expect(value2).toEqual(new Uint8Array(0)); - }); - - test('a small buffer', () => { - const encoder = new BencodeEncoder(new Writer()); - const data = encoder.encode(new Uint8Array([4, 5, 6])); - decoder.reader.reset(data); - const value = decoder.readBin(); - expect(value).toEqual(new Uint8Array([4, 5, 6])); - }); -}); - -describe('array', () => { - test('empty array', () => { - const data = utf8`le`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([]); - }); - - test('array with one number element', () => { - const data = utf8`li1ee`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([1]); - }); - - test('array with strings', () => { - const data = utf8`l1:al1:be1:cl1:d1:eelee`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([utf8`a`, [utf8`b`], utf8`c`, [utf8`d`, utf8`e`], []]); - }); -}); - -describe('object', () => { - test('empty object', () => { - const data = utf8`de`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({}); - }); - - test('object with single key', () => { - const data = utf8`d3:foo3:bare`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({foo: utf8`bar`}); - }); - - test('nested object', () => { - const data = utf8`d0:dee`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({'': {}}); - }); - - test('complex nested object', () => { - const obj = { - a: 1, - b: true, - c: null, - d: [1, 2, 3], - e: { - f: utf8`foo`, - g: utf8`bar`, - h: { - i: utf8`baz`, - j: utf8`qux`, - }, - }, - }; - const data = utf8`d1:ai1e1:bt1:cn1:dli1ei2ei3ee1:ed1:f3:foo1:g3:bar1:hd1:i3:baz1:j3:quxeee`; - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(obj); - }); -}); diff --git a/src/json-pack/bencode/__tests__/BencodeEncoder.spec.ts b/src/json-pack/bencode/__tests__/BencodeEncoder.spec.ts deleted file mode 100644 index 566fb5a8be..0000000000 --- a/src/json-pack/bencode/__tests__/BencodeEncoder.spec.ts +++ /dev/null @@ -1,205 +0,0 @@ -import {utf8} from '../../../util/buffers/strings'; -import {Writer} from '../../../util/buffers/Writer'; -import {PackValue} from '../../types'; -import {BencodeEncoder} from '../BencodeEncoder'; - -const writer = new Writer(32); -const encoder = new BencodeEncoder(writer); - -const assertEncoder = (value: unknown, expected: Uint8Array) => { - const encoded = encoder.encode(value); - expect(encoded).toEqual(expected); -}; - -describe('null', () => { - test('null', () => { - assertEncoder(null, utf8`n`); - }); -}); - -describe('undefined', () => { - test('undefined', () => { - assertEncoder(undefined, utf8`u`); - }); -}); - -describe('boolean', () => { - test('true', () => { - assertEncoder(true, utf8`t`); - }); - - test('false', () => { - assertEncoder(false, utf8`f`); - }); -}); - -describe('number', () => { - test('integers', () => { - assertEncoder(0, utf8`i0e`); - assertEncoder(1, utf8`i1e`); - assertEncoder(-1, utf8`i-1e`); - assertEncoder(123, utf8`i123e`); - assertEncoder(-123, utf8`i-123e`); - assertEncoder(-12321321123, utf8`i-12321321123e`); - assertEncoder(+2321321123, utf8`i2321321123e`); - }); - - test('bigints', () => { - assertEncoder(BigInt('0'), utf8`i0e`); - assertEncoder(BigInt('1'), utf8`i1e`); - assertEncoder(BigInt('-1'), utf8`i-1e`); - assertEncoder(BigInt('123456'), utf8`i123456e`); - assertEncoder(BigInt('-123456'), utf8`i-123456e`); - }); - - test('floats', () => { - assertEncoder(0.0, utf8`i0e`); - assertEncoder(1.1, utf8`i1e`); - assertEncoder(-1.45, utf8`i-1e`); - assertEncoder(123.34, utf8`i123e`); - assertEncoder(-123.234, utf8`i-123e`); - assertEncoder(-12321.321123, utf8`i-12321e`); - assertEncoder(+2321321.123, utf8`i2321321e`); - }); -}); - -describe('string', () => { - test('empty string', () => { - assertEncoder('', utf8`0:`); - }); - - test('one char strings', () => { - assertEncoder('a', utf8`1:a`); - assertEncoder('b', utf8`1:b`); - assertEncoder('z', utf8`1:z`); - assertEncoder('~', utf8`1:~`); - assertEncoder('"', utf8`1:"`); - assertEncoder('\\', utf8`1:\\`); - assertEncoder('*', utf8`1:*`); - assertEncoder('@', utf8`1:@`); - assertEncoder('9', utf8`1:9`); - }); - - test('short strings', () => { - assertEncoder('abc', utf8`3:abc`); - assertEncoder('abc123', utf8`6:abc123`); - }); - - test('long strings', () => { - const txt = - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.'; - assertEncoder(txt, utf8(`${txt.length}:${txt}`)); - }); -}); - -describe('binary', () => { - test('empty blob', () => { - assertEncoder(new Uint8Array(0), utf8`0:`); - }); - - test('small blob', () => { - assertEncoder(new Uint8Array([65]), utf8`1:A`); - }); -}); - -describe('array', () => { - test('empty array', () => { - assertEncoder([], utf8`le`); - }); - - test('array with one integer element', () => { - assertEncoder([1], utf8`li1ee`); - }); - - test('array with two integer elements', () => { - assertEncoder([1, 2], utf8`li1ei2ee`); - }); - - test('array of array', () => { - assertEncoder([[123]], utf8`lli123eee`); - }); - - test('array of various types', () => { - assertEncoder([0, 1.32, 'str', [1, 2, 3]], utf8`li0ei1e3:strli1ei2ei3eee`); - }); -}); - -describe('set', () => { - test('empty array', () => { - assertEncoder(new Set(), utf8`le`); - }); - - test('array with one integer element', () => { - assertEncoder(new Set([1]), utf8`li1ee`); - }); - - test('array with two integer elements', () => { - assertEncoder(new Set([1, 2]), utf8`li1ei2ee`); - }); - - test('array of array', () => { - assertEncoder(new Set([new Set([123])]), utf8`lli123eee`); - }); - - test('array of various types', () => { - assertEncoder(new Set([0, 1.32, 'str', new Set([1, 2, 3])]), utf8`li0ei1e3:strli1ei2ei3eee`); - }); -}); - -describe('object', () => { - test('empty object', () => { - assertEncoder({}, utf8`de`); - }); - - test('object with one key', () => { - assertEncoder({foo: 'bar'}, utf8`d3:foo3:bare`); - }); - - test('object with two keys (sorted)', () => { - assertEncoder({foo: 'bar', baz: 123}, utf8`d3:bazi123e3:foo3:bare`); - }); - - test('object with various nested types', () => { - assertEncoder( - { - str: 'qwerty', - num: 123, - arr: [1, 2, 3], - obj: {foo: 'bar'}, - }, - utf8`d3:arrli1ei2ei3ee3:numi123e3:objd3:foo3:bare3:str6:qwertye`, - ); - }); -}); - -describe('map', () => { - test('empty object', () => { - assertEncoder(new Map(), utf8`de`); - }); - - test('object with one key', () => { - assertEncoder(new Map([['foo', 'bar']]), utf8`d3:foo3:bare`); - }); - - test('object with two keys (sorted)', () => { - assertEncoder( - new Map([ - ['foo', 'bar'], - ['baz', 123], - ]), - utf8`d3:bazi123e3:foo3:bare`, - ); - }); - - test('object with various nested types', () => { - assertEncoder( - new Map([ - ['str', 'qwerty'], - ['num', 123], - ['arr', [1, 2, 3]], - ['obj', {foo: 'bar'}], - ]), - utf8`d3:arrli1ei2ei3ee3:numi123e3:objd3:foo3:bare3:str6:qwertye`, - ); - }); -}); diff --git a/src/json-pack/bencode/__tests__/automated.spec.ts b/src/json-pack/bencode/__tests__/automated.spec.ts deleted file mode 100644 index 858394c780..0000000000 --- a/src/json-pack/bencode/__tests__/automated.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {BencodeEncoder} from '../BencodeEncoder'; -import {BencodeDecoder} from '../BencodeDecoder'; -import {utf8} from '../../../util/buffers/strings'; - -const writer = new Writer(8); -const encoder = new BencodeEncoder(writer); -const decoder = new BencodeDecoder(); - -const documents: [value: unknown, name?: string][] = [ - [0], - [1], - [12345], - [-12345], - [-4444444444444444], - [true], - [false], - [null], - [undefined], - [utf8``, 'empty byte string'], - [utf8`hello`, '"hello" byte string'], - [{}, 'empty object'], - [[], 'empty array'], - [[1, -2, null, true, utf8`asdf`, false, utf8``, undefined], 'array with basic values'], - [[[[]]], 'triply nested arrays'], - [[1, [1, [1], 1], 1], 'nested arrays with values'], - [{a: {b: {c: {d: {foo: utf8`bar`}}}}}, 'nested objects'], -]; - -const assertEncoder = (value: unknown) => { - const encoded = encoder.encode(value); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(value); -}; - -describe('Sample JSON documents', () => { - for (const [value, name] of documents) { - test(name || String(value), () => { - assertEncoder(value); - }); - } -}); diff --git a/src/json-pack/bencode/types.ts b/src/json-pack/bencode/types.ts deleted file mode 100644 index 7bf66c87ec..0000000000 --- a/src/json-pack/bencode/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type BencodeUint8Array = Uint8Array & {__BRAND__: 'bencode'; __TYPE__: T}; diff --git a/src/json-pack/bson/BsonEncoder.ts b/src/json-pack/bson/BsonEncoder.ts deleted file mode 100644 index 17a669a45c..0000000000 --- a/src/json-pack/bson/BsonEncoder.ts +++ /dev/null @@ -1,381 +0,0 @@ -import { - BsonBinary, - BsonDbPointer, - BsonDecimal128, - BsonFloat, - BsonInt32, - BsonInt64, - BsonJavascriptCode, - BsonMaxKey, - BsonMinKey, - BsonObjectId, - BsonTimestamp, -} from './values'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder} from '../types'; - -export class BsonEncoder implements BinaryJsonEncoder { - constructor(public readonly writer: IWriter & IWriterGrowable) {} - - public encode(value: unknown): Uint8Array { - const writer = this.writer; - writer.reset(); - this.writeAny(value); - return writer.flush(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'object': { - if (value === null) throw new Error('NOT_OBJ'); - return this.writeObj(>value); - } - } - throw new Error('NOT_OBJ'); - } - - public writeNull(): void { - throw new Error('Method not implemented.'); - } - - public writeUndef(): void { - throw new Error('Method not implemented.'); - } - - public writeBoolean(bool: boolean): void { - throw new Error('Method not implemented.'); - } - - public writeNumber(num: number): void { - throw new Error('Method not implemented.'); - } - - public writeInteger(int: number): void { - throw new Error('Method not implemented.'); - } - - public writeUInteger(uint: number): void { - throw new Error('Method not implemented.'); - } - - public writeInt32(int: number): void { - const writer = this.writer; - writer.ensureCapacity(4); - writer.view.setInt32(writer.x, int, true); - writer.x += 4; - } - - public writeInt64(int: number | bigint): void { - const writer = this.writer; - writer.ensureCapacity(8); - writer.view.setBigInt64(writer.x, BigInt(int), true); - writer.x += 8; - } - - public writeFloat(float: number): void { - const writer = this.writer; - writer.ensureCapacity(4); - writer.view.setFloat64(writer.x, float, true); - writer.x += 8; - } - - public writeBigInt(int: bigint): void { - throw new Error('Method not implemented.'); - } - - public writeBin(buf: Uint8Array): void { - const length = buf.length; - this.writeInt32(length); - const writer = this.writer; - writer.u8(0); - writer.buf(buf, length); - } - - public writeStr(str: string): void { - const writer = this.writer; - const length = str.length; - const maxSize = 4 + 1 + 4 * length; - writer.ensureCapacity(maxSize); - const x = writer.x; - this.writeInt32(length + 1); - const bytesWritten = writer.utf8(str); - writer.u8(0); - if (bytesWritten !== length) { - writer.view.setInt32(x, bytesWritten + 1, true); - } - } - - public writeAsciiStr(str: string): void { - throw new Error('Method not implemented.'); - } - - public writeArr(arr: unknown[]): void { - this.writeObj(arr as unknown as Record); - } - - public writeObj(obj: Record): void { - const writer = this.writer; - writer.ensureCapacity(8); - const x0 = writer.x0; - const dx = writer.x - x0; - writer.x += 4; - const keys = Object.keys(obj); - const length = keys.length; - for (let i = 0; i < length; i++) { - const key = keys[i]; - const value = obj[key]; - this.writeKey(key, value); - } - writer.u8(0); - const x = writer.x0 + dx; - const size = writer.x - x; - writer.view.setUint32(x, size, true); - } - - public writeCString(str: string): void { - const writer = this.writer; - const length = str.length; - writer.ensureCapacity(1 + 4 * length); - const uint8 = writer.uint8; - let x = writer.x; - let pos = 0; - while (pos < length) { - let value = str.charCodeAt(pos++); - if ((value & 0xffffff80) === 0) { - if (!value) break; - uint8[x++] = value; - continue; - } else if ((value & 0xfffff800) === 0) { - const octet = ((value >> 6) & 0x1f) | 0xc0; - if (!octet) break; - uint8[x++] = octet; - } else { - if (value >= 0xd800 && value <= 0xdbff) { - if (pos < length) { - const extra = str.charCodeAt(pos); - if ((extra & 0xfc00) === 0xdc00) { - pos++; - value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; - } - } - } - if ((value & 0xffff0000) === 0) { - const octet1 = ((value >> 12) & 0x0f) | 0xe0; - const octet2 = ((value >> 6) & 0x3f) | 0x80; - if (!octet1 || !octet2) throw new Error('INVALID_CSTRING'); - uint8[x++] = octet1; - uint8[x++] = octet2; - } else { - const octet1 = ((value >> 18) & 0x07) | 0xf0; - const octet2 = ((value >> 12) & 0x3f) | 0x80; - const octet3 = ((value >> 6) & 0x3f) | 0x80; - if (!octet1 || !octet2 || !octet3) throw new Error('INVALID_CSTRING'); - uint8[x++] = octet1; - uint8[x++] = octet2; - uint8[x++] = octet3; - } - } - const octet = (value & 0x3f) | 0x80; - if (!octet) break; - uint8[x++] = octet; - } - uint8[x++] = 0; - writer.x = x; - } - - public writeObjectId(id: BsonObjectId): void { - const writer = this.writer; - writer.ensureCapacity(12); - const uint8 = writer.uint8; - const x = writer.x; - const {timestamp, process, counter} = id; - uint8[x + 0] = timestamp >>> 24; - uint8[x + 1] = (timestamp >>> 16) & 0xff; - uint8[x + 2] = (timestamp >>> 8) & 0xff; - uint8[x + 3] = timestamp & 0xff; - uint8[x + 4] = process & 0xff; - uint8[x + 5] = (process >>> 8) & 0xff; - uint8[x + 6] = (process >>> 16) & 0xff; - uint8[x + 7] = (process >>> 24) & 0xff; - let lo32 = process | 0; - if (lo32 < 0) lo32 += 4294967296; - const hi32 = (process - lo32) / 4294967296; - uint8[x + 8] = hi32 & 0xff; - uint8[x + 9] = counter >>> 16; - uint8[x + 10] = (counter >>> 8) & 0xff; - uint8[x + 11] = counter & 0xff; - writer.x += 12; - } - - public writeKey(key: string, value: unknown): void { - const writer = this.writer; - switch (typeof value) { - case 'number': { - const isFloat = Math.floor(value) !== value; - if (isFloat) { - writer.u8(0x01); - this.writeCString(key); - this.writeFloat(value); - break; - } - if (value <= 2147483647 && value >= -2147483648) { - writer.u8(0x10); - this.writeCString(key); - this.writeInt32(value); - break; - } - writer.u8(0x12); - this.writeCString(key); - this.writeInt64(value); - break; - } - case 'string': { - writer.u8(0x02); - this.writeCString(key); - this.writeStr(value); - break; - } - case 'object': { - if (value === null) { - writer.u8(0x0a); - this.writeCString(key); - break; - } - const constructor = value.constructor; - switch (constructor) { - case Object: { - writer.u8(0x03); - this.writeCString(key); - this.writeObj(value as Record); - break; - } - case Array: { - writer.u8(0x04); - this.writeCString(key); - this.writeObj(value as Record); - break; - } - case Uint8Array: { - writer.u8(0x05); - this.writeCString(key); - this.writeBin(value as Uint8Array); - break; - } - case BsonObjectId: { - writer.u8(0x07); - this.writeCString(key); - this.writeObjectId(value as BsonObjectId); - break; - } - case Date: { - writer.u8(0x09); - this.writeCString(key); - writer.ensureCapacity(8); - writer.view.setBigUint64(writer.x, BigInt((value as Date).getTime()), true); - writer.x += 8; - break; - } - case RegExp: { - writer.u8(0x0b); - this.writeCString(key); - this.writeCString((value).source); - this.writeCString((value).flags); - break; - } - case BsonDbPointer: { - writer.u8(0x0c); - this.writeCString(key); - const pointer = value as BsonDbPointer; - this.writeStr(pointer.name); - this.writeObjectId(pointer.id); - break; - } - case BsonJavascriptCode: { - writer.u8(0x0d); - this.writeCString(key); - this.writeStr((value as BsonJavascriptCode).code); - break; - } - case BsonInt32: { - writer.u8(0x10); - this.writeCString(key); - this.writeInt32((value as BsonInt32).value); - break; - } - case BsonInt64: { - writer.u8(0x12); - this.writeCString(key); - this.writeInt64((value as BsonInt32).value); - break; - } - case BsonFloat: { - writer.u8(0x01); - this.writeCString(key); - this.writeFloat((value as BsonInt32).value); - break; - } - case BsonTimestamp: { - writer.u8(0x11); - this.writeCString(key); - const ts = value as BsonTimestamp; - this.writeInt32(ts.increment); - this.writeInt32(ts.timestamp); - break; - } - case BsonDecimal128: { - writer.u8(0x13); - this.writeCString(key); - const dec = value as BsonDecimal128; - if (dec.data.length !== 16) throw new Error('INVALID_DECIMAL128'); - writer.buf(dec.data, 16); - break; - } - case BsonMinKey: { - writer.u8(0xff); - this.writeCString(key); - break; - } - case BsonMaxKey: { - writer.u8(0x7f); - this.writeCString(key); - break; - } - case BsonBinary: { - writer.u8(0x05); - this.writeCString(key); - const bin = value as BsonBinary; - const length = bin.data.length; - this.writeInt32(length); - writer.u8(bin.subtype); - writer.buf(bin.data, length); - break; - } - default: { - writer.u8(0x03); - this.writeCString(key); - this.writeObj(value as Record); - break; - } - } - break; - } - case 'boolean': { - writer.u8(0x08); - this.writeCString(key); - writer.u8(+value); - break; - } - case 'undefined': { - writer.u8(0x06); - this.writeCString(key); - break; - } - case 'symbol': { - writer.u8(0x0e); - this.writeCString(key); - this.writeStr(value.description || ''); - break; - } - } - } -} diff --git a/src/json-pack/bson/README.md b/src/json-pack/bson/README.md deleted file mode 100644 index 1dc37ff8fe..0000000000 --- a/src/json-pack/bson/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# BSON - -Performant impelementation of [BSON][bson] (Binary JSON) for JavaScript. - -[bson]: https://bsonspec.org/ - - -## Benchmarks - -``` -npx ts-node benchmarks/json-pack/bench.bson.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.4.0 , Arch: arm64 , CPU: Apple M1 ------------------------------------------------------------------------------ Combined, 63374 bytes -👍 json-joy/json-pack JsonEncoder x 4,604 ops/sec ±0.12% (100 runs sampled) -👎 json-joy/json-pack BsonEncoder x 3,962 ops/sec ±0.18% (100 runs sampled) -👎 bson BSON.serialize() x 1,439 ops/sec ±0.19% (100 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 1,699 ops/sec ±0.11% (100 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder ----------------------------------------------------------------------------- Small object, 53 bytes -👍 json-joy/json-pack JsonEncoder x 4,464,852 ops/sec ±0.47% (96 runs sampled) -👎 json-joy/json-pack BsonEncoder x 3,684,236 ops/sec ±0.18% (100 runs sampled) -👎 bson BSON.serialize() x 884,917 ops/sec ±0.14% (99 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 1,153,616 ops/sec ±0.16% (98 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder ------------------------------------------------------------------------- Typical object, 1002 bytes -👍 json-joy/json-pack JsonEncoder x 306,241 ops/sec ±0.22% (100 runs sampled) -👎 json-joy/json-pack BsonEncoder x 368,051 ops/sec ±0.17% (100 runs sampled) -👎 bson BSON.serialize() x 106,583 ops/sec ±0.84% (99 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 126,497 ops/sec ±0.12% (99 runs sampled) -Fastest is 👎 json-joy/json-pack BsonEncoder --------------------------------------------------------------------------- Large object, 3750 bytes -👍 json-joy/json-pack JsonEncoder x 91,646 ops/sec ±0.76% (100 runs sampled) -👎 json-joy/json-pack BsonEncoder x 109,402 ops/sec ±0.17% (100 runs sampled) -👎 bson BSON.serialize() x 35,037 ops/sec ±0.19% (98 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 39,504 ops/sec ±0.49% (101 runs sampled) -Fastest is 👎 json-joy/json-pack BsonEncoder --------------------------------------------------------------------- Very large object, 45759 bytes -👍 json-joy/json-pack JsonEncoder x 6,234 ops/sec ±0.47% (99 runs sampled) -👎 json-joy/json-pack BsonEncoder x 4,824 ops/sec ±0.20% (99 runs sampled) -👎 bson BSON.serialize() x 1,645 ops/sec ±0.17% (101 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 2,696 ops/sec ±0.66% (98 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder ------------------------------------------------------------------- Object with many keys, 978 bytes -👍 json-joy/json-pack JsonEncoder x 260,571 ops/sec ±0.68% (96 runs sampled) -👎 json-joy/json-pack BsonEncoder x 243,776 ops/sec ±0.42% (98 runs sampled) -👎 bson BSON.serialize() x 86,641 ops/sec ±0.29% (100 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 81,730 ops/sec ±0.13% (99 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder -------------------------------------------------------------------------- String ladder, 4046 bytes -👍 json-joy/json-pack JsonEncoder x 92,381 ops/sec ±0.13% (100 runs sampled) -👎 json-joy/json-pack BsonEncoder x 127,132 ops/sec ±1.03% (90 runs sampled) -👎 bson BSON.serialize() x 75,356 ops/sec ±1.18% (94 runs sampled) -👍 bson Buffer.from(EJSON.stringify()) x 47,308 ops/sec ±0.08% (101 runs sampled) -Fastest is 👎 json-joy/json-pack BsonEncoder -``` diff --git a/src/json-pack/bson/__tests__/BsonEncoder-values.spec.ts b/src/json-pack/bson/__tests__/BsonEncoder-values.spec.ts deleted file mode 100644 index 16f5d489c7..0000000000 --- a/src/json-pack/bson/__tests__/BsonEncoder-values.spec.ts +++ /dev/null @@ -1,154 +0,0 @@ -import {BSON, Decimal128, MinKey, MaxKey} from 'bson'; -import {Writer} from '../../../util/buffers/Writer'; -import {BsonEncoder} from '../BsonEncoder'; -import { - BsonBinary, - BsonDbPointer, - BsonFloat, - BsonInt32, - BsonInt64, - BsonJavascriptCode, - BsonJavascriptCodeWithScope, - BsonMaxKey, - BsonMinKey, - BsonObjectId, - BsonTimestamp, -} from '../values'; -import {BsonDecimal128} from '../values'; - -const writer = new Writer(8); -const encoder = new BsonEncoder(writer); - -describe('special value encoding', () => { - test('BsonObjectId', () => { - const value = { - foo: new BsonObjectId(0x01020304, 0x0102030405, 0x010203), - }; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - const objectId = decoded.foo; - expect(objectId.getTimestamp().getTime()).toBe(0x01020304 * 1000); - }); - - test('Date', () => { - const date = new Date(1689235374326); - const value = {date}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.date.getTime()).toBe(1689235374326); - }); - - test('RegExp', () => { - const reg = /foo/i; - const value = {reg}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.reg.source).toBe('foo'); - expect(decoded.reg.flags).toBe('i'); - }); - - test('BsonDbPointer', () => { - const id = new BsonObjectId(0x01020304, 0x0102030405, 0x010203); - const pointer = new BsonDbPointer('test', id); - const value = {pointer}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.pointer.collection).toBe('test'); - expect(decoded.pointer.oid.getTimestamp().getTime()).toBe(0x01020304 * 1000); - }); - - test('BsonJavascriptCode', () => { - const code = new BsonJavascriptCode('console.log("hello world")'); - const value = {code}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.code.code).toBe('console.log("hello world")'); - }); - - test('BsonJavascriptCodeWithScope', () => { - const code = new BsonJavascriptCodeWithScope('console.log("hello world")', {foo: 'bar'}); - const value = {code}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.code.code).toBe('console.log("hello world")'); - expect(decoded.code.scope).toStrictEqual({foo: 'bar'}); - }); - - test('Symbol', () => { - const symbol = Symbol('foo'); - const value = {symbol}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.symbol).toBe('foo'); - }); - - test('BsonInt32', () => { - const int = new BsonInt32(123); - const value = {int}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.int).toBe(123); - }); - - test('BsonInt64', () => { - const int = new BsonInt64(123); - const value = {int}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.int).toBe(123); - }); - - test('BsonFloat', () => { - const int = new BsonFloat(123); - const value = {int}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.int).toBe(123); - }); - - test('BsonTimestamp', () => { - const increment = 0x01020304; - const timestamp = 0x40302010; - const ts = new BsonTimestamp(increment, timestamp); - const value = {ts}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.ts.toExtendedJSON().$timestamp.t).toBe(timestamp); - expect(decoded.ts.toExtendedJSON().$timestamp.i).toBe(increment); - }); - - test('BsonDecimal128', () => { - const dec = new BsonDecimal128(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])); - const value = {dec}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.dec).toBeInstanceOf(Decimal128); - }); - - test('BsonMinKey and BsonMaxKey', () => { - const value = { - min: new BsonMinKey(), - max: new BsonMaxKey(), - }; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.min).toBeInstanceOf(MinKey); - expect(decoded.max).toBeInstanceOf(MaxKey); - }); - - test('BsonBinary', () => { - const value = { - bin1: new BsonBinary(0x00, new Uint8Array([1, 2, 3])), - bin2: new BsonBinary(0x01, new Uint8Array([1, 2, 3])), - bin3: new BsonBinary(0x80, new Uint8Array([1, 2, 3])), - }; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded.bin1.sub_type).toBe(0); - expect(decoded.bin2.sub_type).toBe(0x01); - expect(decoded.bin3.sub_type).toBe(0x80); - expect(decoded.bin1.buffer).toStrictEqual(Buffer.from([1, 2, 3])); - expect(decoded.bin2.buffer).toStrictEqual(Buffer.from([1, 2, 3])); - expect(decoded.bin3.buffer).toStrictEqual(Buffer.from([1, 2, 3])); - }); -}); diff --git a/src/json-pack/bson/__tests__/BsonEncoder.spec.ts b/src/json-pack/bson/__tests__/BsonEncoder.spec.ts deleted file mode 100644 index e1a86b6318..0000000000 --- a/src/json-pack/bson/__tests__/BsonEncoder.spec.ts +++ /dev/null @@ -1,258 +0,0 @@ -import {BSON} from 'bson'; -import {Writer} from '../../../util/buffers/Writer'; -import {BsonEncoder} from '../BsonEncoder'; - -const writer = new Writer(8); -const encoder = new BsonEncoder(writer); - -const assertEncoder = (value: unknown, expected: unknown = value) => { - if (!value || typeof value !== 'object' || value.constructor !== Object) expected = value = {value}; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded).toEqual(expected); -}; - -describe('undefined', () => { - test('undefined', () => { - assertEncoder(undefined as any); - }); -}); - -describe('null', () => { - test('null', () => { - assertEncoder(null); - }); -}); - -describe('boolean', () => { - test('true', () => { - assertEncoder(true); - }); - - test('false', () => { - assertEncoder(false); - }); -}); - -describe('number', () => { - const ints = [ - 0, 1, -1, 123, -123, 1234, 3333, -3467, -4444, 55555, -55565, 234234, -322324, 2147483647, -1147483647, 12321321123, - -12321321123, +2321321123, - ]; - for (const int of ints) { - test('integer ' + int, () => { - assertEncoder(int); - }); - } - - test('floats', () => { - assertEncoder(0.0); - assertEncoder(1.1); - assertEncoder(-1.45); - assertEncoder(123.34); - assertEncoder(-123.234); - assertEncoder(-12321.321123); - assertEncoder(+2321321.123); - }); -}); - -describe('string', () => { - test('empty string', () => { - assertEncoder(''); - }); - - test('one char strings', () => { - assertEncoder('a'); - assertEncoder('b'); - assertEncoder('z'); - assertEncoder('~'); - assertEncoder('"'); - assertEncoder('\\'); - assertEncoder('*'); - assertEncoder('@'); - assertEncoder('9'); - assertEncoder('✅'); - assertEncoder('👍'); - }); - - test('short strings', () => { - assertEncoder('abc'); - assertEncoder('abc123'); - }); - - test('long strings', () => { - assertEncoder( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.', - ); - }); - - test('unsafe character in the middle of a string', () => { - assertEncoder('...................".....................'); - }); - - test('unsafe character in the middle of a string - 2', () => { - assertEncoder('...................🎉.....................'); - }); -}); - -describe('array', () => { - test('empty array', () => { - assertEncoder([]); - }); - - test('array with one element', () => { - assertEncoder([1]); - }); - - test('array with two elements', () => { - assertEncoder([1, 2]); - }); - - test('array of array', () => { - assertEncoder([[123]]); - }); - - test('array of various types', () => { - assertEncoder([0, 1.32, 'str', true, false, null, [1, 2, 3]]); - }); -}); - -describe('object', () => { - test('empty object', () => { - assertEncoder({}); - }); - - test('object with float key', () => { - assertEncoder({ - float: 123.456, - }); - }); - - test('object with int32 key', () => { - assertEncoder({ - int: 0x01020304, - }); - }); - - test('object with int64 key', () => { - assertEncoder({ - int64: 0x010203040506, - }); - }); - - test('object with one string key', () => { - assertEncoder({foo: 'bar'}); - }); - - test('object with two keys', () => { - assertEncoder({foo: 'bar', baz: 123}); - }); - - test('empty nested array', () => { - assertEncoder({ - foo: [], - }); - }); - - test('simple nested array', () => { - assertEncoder({ - foo: [1, 2, 3], - }); - }); - - test('one nested object', () => { - assertEncoder({ - foo: {}, - }); - }); - - test('nested objects', () => { - assertEncoder({ - foo: { - bar: { - baz: 123, - }, - }, - }); - }); - - test('binary Uint8Array', () => { - const value = { - foo: new Uint8Array([1, 2, 3]), - }; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - const buf = decoded.foo.buffer; - const uint8 = new Uint8Array(buf, buf.byteOffset, buf.byteLength); - expect(uint8).toEqual(value.foo); - }); - - test('undefined key', () => { - assertEncoder({ - foo: undefined, - }); - }); - - test('boolean keys', () => { - assertEncoder({ - true: true, - false: false, - }); - }); - - test('null keys', () => { - assertEncoder({ - null: null, - }); - }); - - test('symbol keys', () => { - const value = { - foo: Symbol('foo'), - }; - const encoded = encoder.encode(value); - const decoded = BSON.deserialize(encoded); - expect(decoded).toStrictEqual({foo: 'foo'}); - }); - - test('object with various nested types', () => { - assertEncoder({ - '': null, - null: false, - true: true, - str: 'asdfasdf ,asdf asdf asdf asdf asdf, asdflkasjdflakjsdflajskdlfkasdf', - num: 123, - arr: [1, 2, 3], - obj: {foo: 'bar'}, - obj2: {1: 2, 3: 4}, - }); - }); -}); - -describe('nested object', () => { - test('large array/object', () => { - assertEncoder({ - foo: [ - 1, - 2, - 3, - { - looongLoooonnnngggg: 'bar', - looongLoooonnnngggg2: 'bar', - looongLoooonnnngggg3: 'bar', - looongLoooonnnngggg4: 'bar', - looongLoooonnnngggg5: 'bar', - looongLoooonnnngggg6: 'bar', - looongLoooonnnngggg7: 'bar', - someVeryVeryLongKeyNameSuperDuperLongKeyName: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName1: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName2: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName3: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName4: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName5: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName6: 'very very long value, I said, very very long value', - }, - ], - }); - }); -}); diff --git a/src/json-pack/bson/__tests__/codec.spec.ts b/src/json-pack/bson/__tests__/codec.spec.ts deleted file mode 100644 index 89bf7f052d..0000000000 --- a/src/json-pack/bson/__tests__/codec.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {BSON} from 'bson'; -import {documents} from '../../../__tests__/json-documents'; -import {BsonEncoder} from '../BsonEncoder'; -import {Writer} from '../../../util/buffers/Writer'; - -const run = (encoder: BsonEncoder) => { - describe('JSON documents', () => { - for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - const json = t.json && typeof t.json === 'object' && t.json.constructor === Object ? t.json : {json: t.json}; - const encoded = encoder.encode(json); - const decoded = BSON.deserialize(encoded); - expect(decoded).toEqual(json); - }); - } - }); -}; - -describe('CbroEncoder', () => { - const writer = new Writer(32); - const encoder = new BsonEncoder(writer); - run(encoder); -}); diff --git a/src/json-pack/bson/index.ts b/src/json-pack/bson/index.ts deleted file mode 100644 index 680858d157..0000000000 --- a/src/json-pack/bson/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './values'; -export * from './BsonEncoder'; diff --git a/src/json-pack/bson/values.ts b/src/json-pack/bson/values.ts deleted file mode 100644 index 1ff8e6f6a5..0000000000 --- a/src/json-pack/bson/values.ts +++ /dev/null @@ -1,63 +0,0 @@ -export class BsonObjectId { - public constructor( - public timestamp: number, - public process: number, - public counter: number, - ) {} -} - -export class BsonDbPointer { - public constructor( - public name: string, - public id: BsonObjectId, - ) {} -} - -export class BsonJavascriptCode { - public constructor(public code: string) {} -} - -export class BsonSymbol { - public constructor(public symbol: string) {} -} - -export class BsonJavascriptCodeWithScope { - public constructor( - public code: string, - public scope: Record, - ) {} -} - -export class BsonInt32 { - public constructor(public value: number) {} -} - -export class BsonInt64 { - public constructor(public value: number) {} -} - -export class BsonFloat { - public constructor(public value: number) {} -} - -export class BsonTimestamp { - public constructor( - public increment: number, - public timestamp: number, - ) {} -} - -export class BsonDecimal128 { - public constructor(public data: Uint8Array) {} -} - -export class BsonMinKey {} - -export class BsonMaxKey {} - -export class BsonBinary { - public constructor( - public subtype: number, - public data: Uint8Array, - ) {} -} diff --git a/src/json-pack/cbor/CborDecoder.ts b/src/json-pack/cbor/CborDecoder.ts deleted file mode 100644 index 64b925799f..0000000000 --- a/src/json-pack/cbor/CborDecoder.ts +++ /dev/null @@ -1,408 +0,0 @@ -import {CONST, ERROR, MAJOR} from './constants'; -import {CborDecoderBase} from './CborDecoderBase'; -import {JsonPackValue} from '../JsonPackValue'; -import type {Path} from '../../json-pointer'; -import type {IReader, IReaderResettable} from '../../util/buffers'; - -export class CborDecoder< - R extends IReader & IReaderResettable = IReader & IReaderResettable, -> extends CborDecoderBase { - // -------------------------------------------------------------- Map reading - - public readAsMap(): Map { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - switch (major) { - case MAJOR.MAP: - return this.readMap(minor); - default: - throw ERROR.UNEXPECTED_MAJOR; - } - } - - public readMap(minor: number): Map { - const length = this.readMinorLen(minor); - if (length >= 0) return this.readMapRaw(length); - else return this.readMapIndef(); - } - - public readMapRaw(length: number): Map { - const map: Map = new Map(); - for (let i = 0; i < length; i++) { - const key = this.val(); - const value = this.val(); - map.set(key, value); - } - return map; - } - - public readMapIndef(): Map { - const map: Map = new Map(); - while (this.reader.peak() !== CONST.END) { - const key = this.val(); - if (this.reader.peak() === CONST.END) throw ERROR.UNEXPECTED_OBJ_BREAK; - const value = this.val(); - map.set(key, value); - } - this.reader.x++; - return map; - } - - // ----------------------------------------------------------- Value skipping - - public skipN(n: number): void { - for (let i = 0; i < n; i++) this.skipAny(); - } - public skipAny(): void { - this.skipAnyRaw(this.reader.u8()); - } - - public skipAnyRaw(octet: number): void { - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - switch (major) { - case MAJOR.UIN: - case MAJOR.NIN: - this.skipUNint(minor); - break; - case MAJOR.BIN: - this.skipBin(minor); - break; - case MAJOR.STR: - this.skipStr(minor); - break; - case MAJOR.ARR: - this.skipArr(minor); - break; - case MAJOR.MAP: - this.skipObj(minor); - break; - case MAJOR.TKN: - this.skipTkn(minor); - break; - case MAJOR.TAG: - this.skipTag(minor); - break; - } - } - - public skipMinorLen(minor: number): number { - if (minor <= 23) return minor; - switch (minor) { - case 24: - return this.reader.u8(); - case 25: - return this.reader.u16(); - case 26: - return this.reader.u32(); - case 27: - return Number(this.reader.u64()); - case 31: - return -1; - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - // --------------------------------------------------------- Integer skipping - - public skipUNint(minor: number): void { - if (minor <= 23) return; - switch (minor) { - case 24: - return this.reader.skip(1); - case 25: - return this.reader.skip(2); - case 26: - return this.reader.skip(4); - case 27: - return this.reader.skip(8); - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - // ---------------------------------------------------------- Binary skipping - - public skipBin(minor: number): void { - const length = this.skipMinorLen(minor); - if (length >= 0) this.reader.skip(length); - else { - while (this.reader.peak() !== CONST.END) this.skipBinChunk(); - this.reader.x++; - } - } - - public skipBinChunk(): void { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.BIN) throw ERROR.UNEXPECTED_BIN_CHUNK_MAJOR; - if (minor > 27) throw ERROR.UNEXPECTED_BIN_CHUNK_MINOR; - this.skipBin(minor); - } - - // ---------------------------------------------------------- String skipping - - public skipStr(minor: number): void { - const length = this.skipMinorLen(minor); - if (length >= 0) this.reader.skip(length); - else { - while (this.reader.peak() !== CONST.END) this.skipStrChunk(); - this.reader.x++; - } - } - - public skipStrChunk(): void { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.STR) throw ERROR.UNEXPECTED_STR_CHUNK_MAJOR; - if (minor > 27) throw ERROR.UNEXPECTED_STR_CHUNK_MINOR; - this.skipStr(minor); - } - - // ----------------------------------------------------------- Array skipping - - public skipArr(minor: number): void { - const length = this.skipMinorLen(minor); - if (length >= 0) this.skipN(length); - else { - while (this.reader.peak() !== CONST.END) this.skipAny(); - this.reader.x++; - } - } - - // ---------------------------------------------------------- Object skipping - - public skipObj(minor: number): void { - const length = this.readMinorLen(minor); - if (length >= 0) return this.skipN(length * 2); - else { - while (this.reader.peak() !== CONST.END) { - this.skipAny(); - if (this.reader.peak() === CONST.END) throw ERROR.UNEXPECTED_OBJ_BREAK; - this.skipAny(); - } - this.reader.x++; - } - } - - // ------------------------------------------------------------- Tag skipping - - public skipTag(minor: number): void { - const length = this.skipMinorLen(minor); - if (length < 0) throw ERROR.UNEXPECTED_MINOR; - this.skipAny(); - } - - // ----------------------------------------------------------- Token skipping - - public skipTkn(minor: number): void { - switch (minor) { - case 0xf8 & CONST.MINOR_MASK: - this.reader.skip(1); - return; - case 0xf9 & CONST.MINOR_MASK: - this.reader.skip(2); - return; - case 0xfa & CONST.MINOR_MASK: - this.reader.skip(4); - return; - case 0xfb & CONST.MINOR_MASK: - this.reader.skip(8); - return; - } - if (minor <= 23) return; - throw ERROR.UNEXPECTED_MINOR; - } - - // --------------------------------------------------------------- Validation - - /** - * Throws if at given offset in a buffer there is an invalid CBOR value, or - * if the value does not span the exact length specified in `size`. I.e. - * throws if: - * - * - The value is not a valid CBOR value. - * - The value is shorter than `size`. - * - The value is longer than `size`. - * - * @param value Buffer in which to validate CBOR value. - * @param offset Offset at which the value starts. - * @param size Expected size of the value. - */ - public validate(value: Uint8Array, offset: number = 0, size: number = value.length): void { - this.reader.reset(value); - this.reader.x = offset; - const start = offset; - this.skipAny(); - const end = this.reader.x; - if (end - start !== size) throw ERROR.INVALID_SIZE; - } - - // -------------------------------------------- One level reading - any value - - public decodeLevel(value: Uint8Array): unknown { - this.reader.reset(value); - return this.readLevel(); - } - - /** - * Decodes only one level of objects and arrays. Other values are decoded - * completely. - * - * @returns One level of decoded CBOR value. - */ - public readLevel(): unknown { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - switch (major) { - case MAJOR.ARR: - return this.readArrLevel(minor); - case MAJOR.MAP: - return this.readObjLevel(minor); - default: - return super.readAnyRaw(octet); - } - } - - /** - * Decodes primitive values, returns container values as `JsonPackValue`. - * - * @returns A primitive value, or CBOR container value as a blob. - */ - public readPrimitiveOrVal(): unknown | JsonPackValue { - const octet = this.reader.peak(); - const major = octet >> 5; - switch (major) { - case MAJOR.ARR: - case MAJOR.MAP: - return this.readAsValue(); - default: - return this.val(); - } - } - - public readAsValue(): JsonPackValue { - const reader = this.reader; - const start = reader.x; - this.skipAny(); - const end = reader.x; - return new JsonPackValue(reader.uint8.subarray(start, end)); - } - - // ----------------------------------------------- One level reading - object - - public readObjLevel(minor: number): Record { - const length = this.readMinorLen(minor); - if (length >= 0) return this.readObjRawLevel(length); - else return this.readObjIndefLevel(); - } - - public readObjRawLevel(length: number): Record { - const obj: Record = {}; - for (let i = 0; i < length; i++) { - const key = this.key(); - const value = this.readPrimitiveOrVal(); - obj[key] = value; - } - return obj; - } - - public readObjIndefLevel(): Record { - const obj: Record = {}; - while (this.reader.peak() !== CONST.END) { - const key = this.key(); - if (this.reader.peak() === CONST.END) throw ERROR.UNEXPECTED_OBJ_BREAK; - const value = this.readPrimitiveOrVal(); - obj[key] = value; - } - this.reader.x++; - return obj; - } - - // ------------------------------------------------ One level reading - array - - public readArrLevel(minor: number): unknown[] { - const length = this.readMinorLen(minor); - if (length >= 0) return this.readArrRawLevel(length); - return this.readArrIndefLevel(); - } - - public readArrRawLevel(length: number): unknown[] { - const arr: unknown[] = []; - for (let i = 0; i < length; i++) arr.push(this.readPrimitiveOrVal()); - return arr; - } - - public readArrIndefLevel(): unknown[] { - const arr: unknown[] = []; - while (this.reader.peak() !== CONST.END) arr.push(this.readPrimitiveOrVal()); - this.reader.x++; - return arr; - } - - // ---------------------------------------------------------- Shallow reading - - public readHdr(expectedMajor: number): number { - const octet = this.reader.u8(); - const major = octet >> 5; - if (major !== expectedMajor) throw ERROR.UNEXPECTED_MAJOR; - const minor = octet & CONST.MINOR_MASK; - if (minor < 24) return minor; - switch (minor) { - case 24: - return this.reader.u8(); - case 25: - return this.reader.u16(); - case 26: - return this.reader.u32(); - case 27: - return Number(this.reader.u64()); - case 31: - return -1; - } - throw ERROR.UNEXPECTED_MINOR; - } - - public readStrHdr(): number { - return this.readHdr(MAJOR.STR); - } - - public readObjHdr(): number { - return this.readHdr(MAJOR.MAP); - } - - public readArrHdr(): number { - return this.readHdr(MAJOR.ARR); - } - - public findKey(key: string): this { - const size = this.readObjHdr(); - for (let i = 0; i < size; i++) { - const k = this.key(); - if (k === key) return this; - this.skipAny(); - } - throw ERROR.KEY_NOT_FOUND; - } - - public findIndex(index: number): this { - const size = this.readArrHdr(); - if (index >= size) throw ERROR.INDEX_OUT_OF_BOUNDS; - for (let i = 0; i < index; i++) this.skipAny(); - return this; - } - - public find(path: Path): this { - for (let i = 0; i < path.length; i++) { - const segment = path[i]; - if (typeof segment === 'string') this.findKey(segment); - else this.findIndex(segment); - } - return this; - } -} diff --git a/src/json-pack/cbor/CborDecoderBase.ts b/src/json-pack/cbor/CborDecoderBase.ts deleted file mode 100644 index f99bf7f0a5..0000000000 --- a/src/json-pack/cbor/CborDecoderBase.ts +++ /dev/null @@ -1,348 +0,0 @@ -import {CONST, ERROR, MAJOR} from './constants'; -import {decodeF16} from '../../util/buffers/f16'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {JsonPackValue} from '../JsonPackValue'; -import {Reader} from '../../util/buffers/Reader'; -import sharedCachedUtf8Decoder from '../../util/buffers/utf8/sharedCachedUtf8Decoder'; -import type {CachedUtf8Decoder} from '../../util/buffers/utf8/CachedUtf8Decoder'; -import type {IReader, IReaderResettable} from '../../util/buffers'; -import type {BinaryJsonDecoder, PackValue} from '../types'; - -export class CborDecoderBase - implements BinaryJsonDecoder -{ - public constructor( - public reader: R = new Reader() as any, - public readonly keyDecoder: CachedUtf8Decoder = sharedCachedUtf8Decoder, - ) {} - - public read(uint8: Uint8Array): PackValue { - this.reader.reset(uint8); - return this.val() as PackValue; - } - - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.val(); - } - - // -------------------------------------------------------- Any value reading - - public val(): unknown { - const reader = this.reader; - const octet = reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major < MAJOR.ARR) { - if (major < MAJOR.BIN) return major === MAJOR.UIN ? this.readUint(minor) : this.readNint(minor); - else return major === MAJOR.BIN ? this.readBin(minor) : this.readStr(minor); - } else { - if (major < MAJOR.TAG) return major === MAJOR.ARR ? this.readArr(minor) : this.readObj(minor); - else return major === MAJOR.TAG ? this.readTag(minor) : this.readTkn(minor); - } - } - - public readAnyRaw(octet: number): unknown { - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major < MAJOR.ARR) { - if (major < MAJOR.BIN) return major === MAJOR.UIN ? this.readUint(minor) : this.readNint(minor); - else return major === MAJOR.BIN ? this.readBin(minor) : this.readStr(minor); - } else { - if (major < MAJOR.TAG) return major === MAJOR.ARR ? this.readArr(minor) : this.readObj(minor); - else return major === MAJOR.TAG ? this.readTag(minor) : this.readTkn(minor); - } - } - - public readMinorLen(minor: number): number { - if (minor < 24) return minor; - switch (minor) { - case 24: - return this.reader.u8(); - case 25: - return this.reader.u16(); - case 26: - return this.reader.u32(); - case 27: - return Number(this.reader.u64()); - case 31: - return -1; - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - // ----------------------------------------------------- Unsigned int reading - - public readUint(minor: number): number | bigint { - if (minor < 25) { - return minor === 24 ? this.reader.u8() : minor; - } else { - if (minor < 27) { - return minor === 25 ? this.reader.u16() : this.reader.u32(); - } else { - const num = this.reader.u64(); - return num > CONST.MAX_UINT ? num : Number(num); - } - } - } - - // ----------------------------------------------------- Negative int reading - - public readNint(minor: number): number | bigint { - if (minor < 25) { - return minor === 24 ? -this.reader.u8() - 1 : -minor - 1; - } else { - if (minor < 27) { - return minor === 25 ? -this.reader.u16() - 1 : -this.reader.u32() - 1; - } else { - const num = this.reader.u64(); - return num > CONST.MAX_UINT - 1 ? -num - BigInt(1) : -Number(num) - 1; - } - } - } - - // ----------------------------------------------------------- Binary reading - - public readBin(minor: number): Uint8Array { - const reader = this.reader; - if (minor <= 23) return reader.buf(minor); - switch (minor) { - case 24: - return reader.buf(reader.u8()); - case 25: - return reader.buf(reader.u16()); - case 26: - return reader.buf(reader.u32()); - case 27: - return reader.buf(Number(reader.u64())); - case 31: { - let size = 0; - const list: Uint8Array[] = []; - while (this.reader.peak() !== CONST.END) { - const uint8 = this.readBinChunk(); - size += uint8.length; - list.push(uint8); - } - this.reader.x++; - const res = new Uint8Array(size); - let offset = 0; - const length = list.length; - for (let i = 0; i < length; i++) { - const arr = list[i]; - res.set(arr, offset); - offset += arr.length; - } - return res; - } - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - public readBinChunk(): Uint8Array { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.BIN) throw ERROR.UNEXPECTED_BIN_CHUNK_MAJOR; - if (minor > 27) throw ERROR.UNEXPECTED_BIN_CHUNK_MINOR; - return this.readBin(minor); - } - - // ----------------------------------------------------------- String reading - - public readAsStr(): string { - const reader = this.reader; - const octet = reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.STR) throw ERROR.UNEXPECTED_STR_MAJOR; - return this.readStr(minor); - } - - public readStr(minor: number): string { - const reader = this.reader; - if (minor <= 23) return reader.utf8(minor); - switch (minor) { - case 24: - return reader.utf8(reader.u8()); - case 25: - return reader.utf8(reader.u16()); - case 26: - return reader.utf8(reader.u32()); - case 27: - return reader.utf8(Number(reader.u64())); - case 31: { - let str = ''; - while (reader.peak() !== CONST.END) str += this.readStrChunk(); - this.reader.x++; - return str; - } - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - public readStrLen(minor: number): number { - if (minor <= 23) return minor; - switch (minor) { - case 24: - return this.reader.u8(); - case 25: - return this.reader.u16(); - case 26: - return this.reader.u32(); - case 27: - return Number(this.reader.u64()); - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - public readStrChunk(): string { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.STR) throw ERROR.UNEXPECTED_STR_CHUNK_MAJOR; - if (minor > 27) throw ERROR.UNEXPECTED_STR_CHUNK_MINOR; - return this.readStr(minor); - } - - // ------------------------------------------------------------ Array reading - - public readArr(minor: number): unknown[] { - const length = this.readMinorLen(minor); - if (length >= 0) return this.readArrRaw(length); - return this.readArrIndef(); - } - - public readArrRaw(length: number): unknown[] { - const arr: unknown[] = []; - for (let i = 0; i < length; i++) arr.push(this.val()); - return arr; - } - - public readArrIndef(): unknown[] { - const arr: unknown[] = []; - while (this.reader.peak() !== CONST.END) arr.push(this.val()); - this.reader.x++; - return arr; - } - - // ----------------------------------------------------------- Object reading - - public readObj(minor: number): Record { - if (minor < 28) { - let length = minor; - switch (minor) { - case 24: - length = this.reader.u8(); - break; - case 25: - length = this.reader.u16(); - break; - case 26: - length = this.reader.u32(); - break; - case 27: - length = Number(this.reader.u64()); - break; - } - const obj: Record = {}; - for (let i = 0; i < length; i++) { - const key = this.key(); - if (key === '__proto__') throw ERROR.UNEXPECTED_OBJ_KEY; - const value = this.val(); - obj[key] = value; - } - return obj; - } else if (minor === 31) return this.readObjIndef(); - else throw ERROR.UNEXPECTED_MINOR; - } - - /** Remove this? */ - public readObjRaw(length: number): Record { - const obj: Record = {}; - for (let i = 0; i < length; i++) { - const key = this.key(); - const value = this.val(); - obj[key] = value; - } - return obj; - } - - public readObjIndef(): Record { - const obj: Record = {}; - while (this.reader.peak() !== CONST.END) { - const key = this.key(); - if (this.reader.peak() === CONST.END) throw ERROR.UNEXPECTED_OBJ_BREAK; - const value = this.val(); - obj[key] = value; - } - this.reader.x++; - return obj; - } - - public key(): string { - const octet = this.reader.u8(); - const major = octet >> 5; - const minor = octet & CONST.MINOR_MASK; - if (major !== MAJOR.STR) return String(this.readAnyRaw(octet)); - const length = this.readStrLen(minor); - if (length > 31) return this.reader.utf8(length); - const key = this.keyDecoder.decode(this.reader.uint8, this.reader.x, length); - this.reader.skip(length); - return key; - } - - // -------------------------------------------------------------- Tag reading - - public readTag(minor: number): JsonPackExtension | unknown { - if (minor <= 23) return this.readTagRaw(minor); - switch (minor) { - case 24: - return this.readTagRaw(this.reader.u8()); - case 25: - return this.readTagRaw(this.reader.u16()); - case 26: - return this.readTagRaw(this.reader.u32()); - case 27: - return this.readTagRaw(Number(this.reader.u64())); - default: - throw ERROR.UNEXPECTED_MINOR; - } - } - - public readTagRaw(tag: number): JsonPackExtension | unknown { - return new JsonPackExtension(tag, this.val()); - } - - // ------------------------------------------------------------ Token reading - - public readTkn(minor: number): number | true | false | null | undefined | JsonPackValue { - switch (minor) { - case 0xf4 & CONST.MINOR_MASK: - return false; - case 0xf5 & CONST.MINOR_MASK: - return true; - case 0xf6 & CONST.MINOR_MASK: - return null; - case 0xf7 & CONST.MINOR_MASK: - return undefined; - case 0xf8 & CONST.MINOR_MASK: - return new JsonPackValue(this.reader.u8()); - case 0xf9 & CONST.MINOR_MASK: - return this.f16(); - case 0xfa & CONST.MINOR_MASK: - return this.reader.f32(); - case 0xfb & CONST.MINOR_MASK: - return this.reader.f64(); - } - if (minor <= 23) return new JsonPackValue(minor); - throw ERROR.UNEXPECTED_MINOR; - } - - public f16(): number { - return decodeF16(this.reader.u16()); - } -} diff --git a/src/json-pack/cbor/CborDecoderDag.ts b/src/json-pack/cbor/CborDecoderDag.ts deleted file mode 100644 index e1ab74b909..0000000000 --- a/src/json-pack/cbor/CborDecoderDag.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {JsonPackExtension} from '../JsonPackExtension'; -import {CborDecoder} from './CborDecoder'; - -export class CborDecoderDag extends CborDecoder { - public readTagRaw(tag: number): JsonPackExtension | unknown { - const value = this.val(); - return tag === 42 ? new JsonPackExtension(tag, value) : value; - } -} diff --git a/src/json-pack/cbor/CborEncoder.ts b/src/json-pack/cbor/CborEncoder.ts deleted file mode 100644 index facf3d1568..0000000000 --- a/src/json-pack/cbor/CborEncoder.ts +++ /dev/null @@ -1,71 +0,0 @@ -import {isFloat32} from '../../util/buffers/isFloat32'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {CborEncoderFast} from './CborEncoderFast'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import {JsonPackValue} from '../JsonPackValue'; - -export class CborEncoder extends CborEncoderFast { - /** - * Called when the encoder encounters a value that it does not know how to encode. - * - * @param value Some JavaScript value. - */ - public writeUnknown(value: unknown): void { - this.writeNull(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'boolean': - return this.writer.u8(0xf4 + +value); - case 'object': { - if (!value) return this.writer.u8(0xf6); - const constructor = value.constructor; - switch (constructor) { - case Object: - return this.writeObj(value as Record); - case Array: - return this.writeArr(value as unknown[]); - case Uint8Array: - return this.writeBin(value as Uint8Array); - case Map: - return this.writeMap(value as Map); - case JsonPackExtension: - return this.writeTag((value).tag, (value).val); - case JsonPackValue: - const buf = (value as JsonPackValue).val; - return this.writer.buf(buf, buf.length); - default: - return this.writeUnknown(value); - } - } - case 'undefined': - return this.writeUndef(); - case 'bigint': - return this.writeBigInt(value as bigint); - default: - return this.writeUnknown(value); - } - } - - public writeFloat(float: number): void { - if (isFloat32(float)) this.writer.u8f32(0xfa, float); - else this.writer.u8f64(0xfb, float); - } - - public writeMap(map: Map): void { - this.writeMapHdr(map.size); - map.forEach((value, key) => { - this.writeAny(key); - this.writeAny(value); - }); - } - - public writeUndef(): void { - this.writer.u8(0xf7); - } -} diff --git a/src/json-pack/cbor/CborEncoderDag.ts b/src/json-pack/cbor/CborEncoderDag.ts deleted file mode 100644 index 91294852d9..0000000000 --- a/src/json-pack/cbor/CborEncoderDag.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {CborEncoderStable} from './CborEncoderStable'; - -export class CborEncoderDag extends CborEncoderStable { - public writeUndef(): void { - this.writeNull(); - } - - public writeFloat(float: number): void { - if (float !== float) return this.writeNull(); - if (!Number.isFinite(float)) return this.writeNull(); - this.writer.u8f64(0xfb, float); - } - - public writeTag(tag: number, value: unknown): void { - if (tag === 42) this.writeTagHdr(tag); - this.writeAny(value); - } -} diff --git a/src/json-pack/cbor/CborEncoderFast.ts b/src/json-pack/cbor/CborEncoderFast.ts deleted file mode 100644 index b54ff07cc2..0000000000 --- a/src/json-pack/cbor/CborEncoderFast.ts +++ /dev/null @@ -1,333 +0,0 @@ -import {Writer} from '../../util/buffers/Writer'; -import {CONST, MAJOR_OVERLAY} from './constants'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder, StreamingBinaryJsonEncoder, TlvBinaryJsonEncoder} from '../types'; -import type {Slice} from '../../util/buffers/Slice'; - -const isSafeInteger = Number.isSafeInteger; - -/** - * Fast CBOR encoder supports only JSON values. Use regular `CborEncoder` if - * you need ability to encode all CBOR value types. - */ -export class CborEncoderFast - implements BinaryJsonEncoder, StreamingBinaryJsonEncoder, TlvBinaryJsonEncoder -{ - constructor(public readonly writer: W = new Writer() as any) {} - - public encode(value: unknown): Uint8Array { - this.writeAny(value); - return this.writer.flush(); - } - - public encodeToSlice(value: unknown): Slice { - this.writeAny(value); - return this.writer.flushSlice(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'boolean': - return this.writer.u8(0xf4 + +value); - case 'object': { - if (!value) return this.writer.u8(0xf6); - const constructor = value.constructor; - switch (constructor) { - case Array: - return this.writeArr(value as unknown[]); - default: - return this.writeObj(value as Record); - } - } - } - } - - public writeCbor(): void { - this.writer.u8u16(0xd9, 0xd9f7); - } - - public writeEnd(): void { - this.writer.u8(CONST.END); - } - - public writeNull(): void { - this.writer.u8(0xf6); - } - - public writeBoolean(bool: boolean): void { - if (bool) this.writer.u8(0xf5); - else this.writer.u8(0xf4); - } - - public writeNumber(num: number): void { - if (isSafeInteger(num)) this.writeInteger(num); - else if (typeof num === 'bigint') this.writeBigInt(num); - else this.writeFloat(num); - } - - public writeBigInt(int: bigint): void { - if (int >= 0) this.writeBigUint(int); - else this.writeBigSint(int); - } - - public writeBigUint(uint: bigint): void { - if (uint <= Number.MAX_SAFE_INTEGER) return this.writeUInteger(Number(uint)); - this.writer.u8u64(0x1b, uint); - } - - public writeBigSint(int: bigint): void { - if (int >= Number.MIN_SAFE_INTEGER) return this.encodeNint(Number(int)); - const uint = -BigInt(1) - int; - this.writer.u8u64(0x3b, uint); - } - - public writeInteger(int: number): void { - if (int >= 0) this.writeUInteger(int); - else this.encodeNint(int); - } - - public writeUInteger(uint: number): void { - const writer = this.writer; - writer.ensureCapacity(9); - const uint8 = writer.uint8; - let x = writer.x; - if (uint <= 23) { - uint8[x++] = MAJOR_OVERLAY.UIN + uint; - } else if (uint <= 0xff) { - uint8[x++] = 0x18; - uint8[x++] = uint; - } else if (uint <= 0xffff) { - uint8[x++] = 0x19; - writer.view.setUint16(x, uint); - x += 2; - } else if (uint <= 0xffffffff) { - uint8[x++] = 0x1a; - writer.view.setUint32(x, uint); - x += 4; - } else { - uint8[x++] = 0x1b; - writer.view.setBigUint64(x, BigInt(uint)); - x += 8; - } - writer.x = x; - } - - /** @deprecated Remove and use `writeNumber` instead. */ - public encodeNumber(num: number): void { - this.writeNumber(num); - } - - /** @deprecated Remove and use `writeInteger` instead. */ - public encodeInteger(int: number): void { - this.writeInteger(int); - } - - /** @deprecated */ - public encodeUint(uint: number): void { - this.writeUInteger(uint); - } - - public encodeNint(int: number): void { - const uint = -1 - int; - const writer = this.writer; - writer.ensureCapacity(9); - const uint8 = writer.uint8; - let x = writer.x; - if (uint < 24) { - uint8[x++] = MAJOR_OVERLAY.NIN + uint; - } else if (uint <= 0xff) { - uint8[x++] = 0x38; - uint8[x++] = uint; - } else if (uint <= 0xffff) { - uint8[x++] = 0x39; - writer.view.setUint16(x, uint); - x += 2; - } else if (uint <= 0xffffffff) { - uint8[x++] = 0x3a; - writer.view.setUint32(x, uint); - x += 4; - } else { - uint8[x++] = 0x3b; - writer.view.setBigUint64(x, BigInt(uint)); - x += 8; - } - writer.x = x; - } - - public writeFloat(float: number): void { - this.writer.u8f64(0xfb, float); - } - - public writeBin(buf: Uint8Array): void { - const length = buf.length; - this.writeBinHdr(length); - this.writer.buf(buf, length); - } - - public writeBinHdr(length: number): void { - const writer = this.writer; - if (length <= 23) writer.u8(MAJOR_OVERLAY.BIN + length); - else if (length <= 0xff) writer.u16((0x58 << 8) + length); - else if (length <= 0xffff) writer.u8u16(0x59, length); - else if (length <= 0xffffffff) writer.u8u32(0x5a, length); - else writer.u8u64(0x5b, length); - } - - public writeStr(str: string): void { - const writer = this.writer; - const length = str.length; - const maxSize = length * 4; - writer.ensureCapacity(5 + maxSize); - const uint8 = writer.uint8; - let lengthOffset: number = writer.x; - if (maxSize <= 23) writer.x++; - else if (maxSize <= 0xff) { - uint8[writer.x++] = 0x78; - lengthOffset = writer.x; - writer.x++; - } else if (maxSize <= 0xffff) { - uint8[writer.x++] = 0x79; - lengthOffset = writer.x; - writer.x += 2; - } else { - uint8[writer.x++] = 0x7a; - lengthOffset = writer.x; - writer.x += 4; - } - const bytesWritten = writer.utf8(str); - if (maxSize <= 23) uint8[lengthOffset] = MAJOR_OVERLAY.STR + bytesWritten; - else if (maxSize <= 0xff) uint8[lengthOffset] = bytesWritten; - else if (maxSize <= 0xffff) writer.view.setUint16(lengthOffset, bytesWritten); - else writer.view.setUint32(lengthOffset, bytesWritten); - } - - public writeStrHdr(length: number): void { - const writer = this.writer; - if (length <= 23) writer.u8(MAJOR_OVERLAY.STR + length); - else if (length <= 0xff) writer.u16((0x78 << 8) + length); - else if (length <= 0xffff) writer.u8u16(0x79, length); - else writer.u8u32(0x7a, length); - } - - public writeAsciiStr(str: string): void { - this.writeStrHdr(str.length); - this.writer.ascii(str); - } - - public writeArr(arr: unknown[]): void { - const length = arr.length; - this.writeArrHdr(length); - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - } - - public writeArrHdr(length: number): void { - const writer = this.writer; - if (length <= 23) writer.u8(MAJOR_OVERLAY.ARR + length); - else if (length <= 0xff) writer.u16((0x98 << 8) + length); - else if (length <= 0xffff) writer.u8u16(0x99, length); - else if (length <= 0xffffffff) writer.u8u32(0x9a, length); - else writer.u8u64(0x9b, length); - } - - public writeObj(obj: Record): void { - const keys = Object.keys(obj); - const length = keys.length; - this.writeObjHdr(length); - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } - - public writeObjHdr(length: number): void { - const writer = this.writer; - if (length <= 23) writer.u8(MAJOR_OVERLAY.MAP + length); - else if (length <= 0xff) writer.u16((0xb8 << 8) + length); - else if (length <= 0xffff) writer.u8u16(0xb9, length); - else if (length <= 0xffffffff) writer.u8u32(0xba, length); - else writer.u8u64(0xbb, length); - } - - public writeMapHdr(length: number): void { - this.writeObjHdr(length); - } - - public writeStartMap(): void { - this.writer.u8(0xbf); - } - - public writeTag(tag: number, value: unknown): void { - this.writeTagHdr(tag); - this.writeAny(value); - } - - public writeTagHdr(tag: number): void { - const writer = this.writer; - if (tag <= 23) writer.u8(MAJOR_OVERLAY.TAG + tag); - else if (tag <= 0xff) writer.u16((0xd8 << 8) + tag); - else if (tag <= 0xffff) writer.u8u16(0xd9, tag); - else if (tag <= 0xffffffff) writer.u8u32(0xda, tag); - else writer.u8u64(0xdb, tag); - } - - public writeTkn(value: number): void { - const writer = this.writer; - if (value <= 23) writer.u8(MAJOR_OVERLAY.TKN + value); - else if (value <= 0xff) writer.u16((0xf8 << 8) + value); - } - - // ------------------------------------------------------- Streaming encoding - - public writeStartStr(): void { - this.writer.u8(0x7f); - } - - public writeStrChunk(str: string): void { - throw new Error('Not implemented'); - } - - public writeEndStr(): void { - throw new Error('Not implemented'); - } - - public writeStartBin(): void { - this.writer.u8(0x5f); - } - - public writeBinChunk(buf: Uint8Array): void { - throw new Error('Not implemented'); - } - - public writeEndBin(): void { - throw new Error('Not implemented'); - } - - public writeStartArr(): void { - this.writer.u8(0x9f); - } - - public writeArrChunk(item: unknown): void { - throw new Error('Not implemented'); - } - - public writeEndArr(): void { - this.writer.u8(CONST.END); - } - - public writeStartObj(): void { - this.writer.u8(0xbf); - } - - public writeObjChunk(key: string, value: unknown): void { - throw new Error('Not implemented'); - } - - public writeEndObj(): void { - this.writer.u8(CONST.END); - } -} diff --git a/src/json-pack/cbor/CborEncoderStable.ts b/src/json-pack/cbor/CborEncoderStable.ts deleted file mode 100644 index 45359574c4..0000000000 --- a/src/json-pack/cbor/CborEncoderStable.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {CborEncoder} from './CborEncoder'; -import {sort} from '../../util/sort/insertion2'; -import {MAJOR_OVERLAY} from './constants'; -import {objKeyCmp} from '../util/objKeyCmp'; - -const strHeaderLength = (strSize: number): 1 | 2 | 3 | 5 => { - if (strSize <= 23) return 1; - else if (strSize <= 0xff) return 2; - else if (strSize <= 0xffff) return 3; - else return 5; -}; - -export class CborEncoderStable extends CborEncoder { - public writeObj(obj: Record): void { - const keys = Object.keys(obj); - sort(keys, objKeyCmp); - const length = keys.length; - this.writeObjHdr(length); - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } - - /** @todo This implementation might be even faster than the default one, verify that. */ - public writeStr(str: string): void { - const writer = this.writer; - const length = str.length; - const maxSize = length * 4; - writer.ensureCapacity(5 + maxSize); - const headerLengthGuess = strHeaderLength(length); - const x0 = writer.x; - const x1 = x0 + headerLengthGuess; - writer.x = x1; - const bytesWritten = writer.utf8(str); - const uint8 = writer.uint8; - const headerLength = strHeaderLength(bytesWritten); - if (headerLength !== headerLengthGuess) { - const shift = headerLength - headerLengthGuess; - uint8.copyWithin(x1 + shift, x1, x1 + bytesWritten); - } - switch (headerLength) { - case 1: - uint8[x0] = MAJOR_OVERLAY.STR + bytesWritten; - break; - case 2: - uint8[x0] = 0x78; - uint8[x0 + 1] = bytesWritten; - break; - case 3: { - uint8[x0] = 0x79; - writer.view.setUint16(x0 + 1, bytesWritten); - break; - } - case 5: { - uint8[x0] = 0x7a; - writer.view.setUint32(x0 + 1, bytesWritten); - break; - } - } - writer.x = x0 + headerLength + bytesWritten; - } - - public writeUndef(): void { - this.writeNull(); - } -} diff --git a/src/json-pack/cbor/README.md b/src/json-pack/cbor/README.md deleted file mode 100644 index a24fd750e6..0000000000 --- a/src/json-pack/cbor/README.md +++ /dev/null @@ -1,490 +0,0 @@ -# `json-pack` CBOR Codec - - -## Implementation details - -- Map keys are treated as strings. - - To decode a map with non-string keys, use `decoder.readAsMap()` method. - - When encoding JavaScript `Object`, map keys are encoded as strings. - - Full encoder supports `Map` object encoding, where keys can be any type. - - When decoding CBOR, map keys are decoded as strings. If a non-string value - is encountered, it is decoded and cast to a string. -- Half-precision `f16` floats are decoded to JavaScript `number`, however, - encoder does not support half-precision floats—floats are encoded as - `f32` or `f64`. - - -## Benchmarks - -### Encoding - -``` -npx ts-node benchmarks/json-pack/bench.encoding.cbor.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.1.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Small object, 44 bytes -🤞 Buffer.from(JSON.stringify()) x 2,339,523 ops/sec ±0.50% (99 runs sampled) -🤞 JSON.stringify() x 3,802,757 ops/sec ±0.17% (100 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 6,132,816 ops/sec ±0.43% (99 runs sampled) -🤞 json-joy/json-pack CborEncoder x 6,248,575 ops/sec ±0.13% (98 runs sampled) -🤞 cbor-x x 4,924,643 ops/sec ±0.31% (99 runs sampled) -🤞 cbor-js x 670,013 ops/sec ±1.51% (80 runs sampled) -🤞 cborg x 777,829 ops/sec ±0.16% (98 runs sampled) -🤞 cbor-sync x 444,785 ops/sec ±3.07% (96 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -🤞 Buffer.from(JSON.stringify()) x 208,448 ops/sec ±0.07% (101 runs sampled) -🤞 JSON.stringify() x 335,826 ops/sec ±0.14% (101 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 468,552 ops/sec ±0.31% (96 runs sampled) -🤞 json-joy/json-pack CborEncoder x 446,904 ops/sec ±0.15% (98 runs sampled) -🤞 cbor-x x 400,380 ops/sec ±0.89% (91 runs sampled) -🤞 cbor-js x 109,455 ops/sec ±0.13% (98 runs sampled) -🤞 cborg x 60,584 ops/sec ±0.10% (102 runs sampled) -🤞 cbor-sync x 75,523 ops/sec ±0.21% (96 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------------- Large object, 3741 bytes -🤞 Buffer.from(JSON.stringify()) x 64,232 ops/sec ±0.07% (99 runs sampled) -🤞 JSON.stringify() x 108,186 ops/sec ±0.24% (101 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 135,553 ops/sec ±0.11% (101 runs sampled) -🤞 json-joy/json-pack CborEncoder x 130,092 ops/sec ±0.24% (100 runs sampled) -🤞 cbor-x x 110,045 ops/sec ±0.63% (95 runs sampled) -🤞 cbor-js x 33,044 ops/sec ±0.11% (102 runs sampled) -🤞 cborg x 18,516 ops/sec ±0.13% (101 runs sampled) -🤞 cbor-sync x 25,829 ops/sec ±0.43% (98 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------- Very large object, 45750 bytes -🤞 Buffer.from(JSON.stringify()) x 7,175 ops/sec ±0.76% (98 runs sampled) -🤞 JSON.stringify() x 7,783 ops/sec ±0.51% (101 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 5,759 ops/sec ±0.53% (100 runs sampled) -🤞 json-joy/json-pack CborEncoder x 5,569 ops/sec ±0.43% (100 runs sampled) -🤞 cbor-x x 5,671 ops/sec ±0.71% (94 runs sampled) -🤞 cbor-js x 2,513 ops/sec ±0.40% (100 runs sampled) -🤞 cborg x 818 ops/sec ±1.04% (92 runs sampled) -🤞 cbor-sync x 1,579 ops/sec ±0.34% (98 runs sampled) -Fastest is 🤞 JSON.stringify() ------------------------------------------------------------------- Object with many keys, 969 bytes -🤞 Buffer.from(JSON.stringify()) x 182,418 ops/sec ±0.69% (99 runs sampled) -🤞 JSON.stringify() x 166,880 ops/sec ±5.89% (82 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 276,754 ops/sec ±1.11% (99 runs sampled) -🤞 json-joy/json-pack CborEncoder x 272,113 ops/sec ±0.77% (94 runs sampled) -🤞 cbor-x x 193,156 ops/sec ±0.49% (96 runs sampled) -🤞 cbor-js x 73,180 ops/sec ±0.38% (100 runs sampled) -🤞 cborg x 35,937 ops/sec ±0.19% (95 runs sampled) -🤞 cbor-sync x 53,410 ops/sec ±0.66% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoderFast -------------------------------------------------------------------------- String ladder, 3398 bytes -🤞 Buffer.from(JSON.stringify()) x 148,910 ops/sec ±0.24% (98 runs sampled) -🤞 JSON.stringify() x 172,582 ops/sec ±0.06% (102 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 276,018 ops/sec ±0.64% (92 runs sampled) -🤞 json-joy/json-pack CborEncoder x 278,835 ops/sec ±0.85% (92 runs sampled) -🤞 cbor-x x 209,737 ops/sec ±0.44% (95 runs sampled) -🤞 cbor-js x 29,304 ops/sec ±0.15% (101 runs sampled) -🤞 cborg x 61,577 ops/sec ±0.10% (102 runs sampled) -🤞 cbor-sync x 73,548 ops/sec ±2.14% (93 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder,🤞 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------------- Long strings, 7011 bytes -🤞 Buffer.from(JSON.stringify()) x 28,860 ops/sec ±0.06% (99 runs sampled) -🤞 JSON.stringify() x 59,800 ops/sec ±0.07% (99 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 403,027 ops/sec ±1.97% (93 runs sampled) -🤞 json-joy/json-pack CborEncoder x 415,001 ops/sec ±1.38% (95 runs sampled) -🤞 cbor-x x 364,240 ops/sec ±1.95% (85 runs sampled) -🤞 cbor-js x 13,370 ops/sec ±0.11% (101 runs sampled) -🤞 cborg x 118,723 ops/sec ±0.54% (99 runs sampled) -🤞 cbor-sync x 117,072 ops/sec ±0.17% (94 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -🤞 Buffer.from(JSON.stringify()) x 1,016,012 ops/sec ±0.12% (102 runs sampled) -🤞 JSON.stringify() x 1,828,820 ops/sec ±0.15% (102 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 1,848,409 ops/sec ±0.56% (99 runs sampled) -🤞 json-joy/json-pack CborEncoder x 1,860,103 ops/sec ±0.18% (98 runs sampled) -🤞 cbor-x x 1,360,519 ops/sec ±0.22% (98 runs sampled) -🤞 cbor-js x 367,320 ops/sec ±0.25% (97 runs sampled) -🤞 cborg x 278,084 ops/sec ±0.15% (98 runs sampled) -🤞 cbor-sync x 181,966 ops/sec ±0.17% (92 runs sampled) -Fastest is 🤞 json-joy/json-pack CborEncoder --------------------------------------------------------------------------------- Numbers, 136 bytes -🤞 Buffer.from(JSON.stringify()) x 1,231,696 ops/sec ±0.15% (100 runs sampled) -🤞 JSON.stringify() x 1,610,733 ops/sec ±0.16% (100 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 2,775,684 ops/sec ±0.17% (101 runs sampled) -🤞 json-joy/json-pack CborEncoder x 3,112,233 ops/sec ±0.18% (100 runs sampled) -🤞 cbor-x x 3,264,422 ops/sec ±0.14% (101 runs sampled) -🤞 cbor-js x 558,877 ops/sec ±1.31% (89 runs sampled) -🤞 cborg x 296,104 ops/sec ±0.14% (100 runs sampled) -🤞 cbor-sync x 379,437 ops/sec ±0.28% (99 runs sampled) -Fastest is 🤞 cbor-x ---------------------------------------------------------------------------------- Tokens, 308 bytes -🤞 Buffer.from(JSON.stringify()) x 1,101,690 ops/sec ±0.17% (98 runs sampled) -🤞 JSON.stringify() x 1,560,523 ops/sec ±0.14% (98 runs sampled) -🤞 json-joy/json-pack CborEncoderFast x 1,352,703 ops/sec ±0.24% (96 runs sampled) -🤞 json-joy/json-pack CborEncoder x 1,371,395 ops/sec ±0.24% (101 runs sampled) -🤞 cbor-x x 1,975,990 ops/sec ±0.19% (98 runs sampled) -🤞 cbor-js x 525,540 ops/sec ±1.25% (91 runs sampled) -🤞 cborg x 227,011 ops/sec ±0.15% (98 runs sampled) -🤞 cbor-sync x 418,451 ops/sec ±0.30% (97 runs sampled) -Fastest is 🤞 cbor-x -``` - -Node 18: - -``` -npx ts-node benchmarks/json-pack/bench.cbor.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 Max ----------------------------------------------------------------------------- Small object, 44 bytes -👍 json-joy/json-pack CborEncoderFast x 6,233,741 ops/sec ±0.48% (97 runs sampled) -👍 json-joy/json-pack CborEncoder x 6,284,071 ops/sec ±0.52% (98 runs sampled) -👍 cborg x 593,217 ops/sec ±0.75% (98 runs sampled) -👍 cbor-x x 4,360,950 ops/sec ±0.61% (92 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -👍 json-joy/json-pack CborEncoderFast x 450,797 ops/sec ±0.43% (94 runs sampled) -👍 json-joy/json-pack CborEncoder x 465,790 ops/sec ±0.39% (97 runs sampled) -👍 cborg x 48,343 ops/sec ±0.57% (99 runs sampled) -👍 cbor-x x 414,580 ops/sec ±0.38% (98 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -👍 json-joy/json-pack CborEncoderFast x 132,873 ops/sec ±0.37% (99 runs sampled) -👍 json-joy/json-pack CborEncoder x 134,572 ops/sec ±0.49% (96 runs sampled) -👍 cborg x 14,615 ops/sec ±0.59% (96 runs sampled) -👍 cbor-x x 114,106 ops/sec ±0.46% (100 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------- Very large object, 45750 bytes -👍 json-joy/json-pack CborEncoderFast x 5,498 ops/sec ±0.60% (97 runs sampled) -👍 json-joy/json-pack CborEncoder x 5,474 ops/sec ±1.15% (94 runs sampled) -👍 cborg x 659 ops/sec ±0.99% (92 runs sampled) -👍 cbor-x x 5,635 ops/sec ±0.76% (96 runs sampled) -Fastest is 👍 cbor-x ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 json-joy/json-pack CborEncoderFast x 279,077 ops/sec ±0.52% (96 runs sampled) -👍 json-joy/json-pack CborEncoder x 279,231 ops/sec ±0.35% (98 runs sampled) -👍 cborg x 26,533 ops/sec ±0.62% (95 runs sampled) -👍 cbor-x x 194,635 ops/sec ±0.58% (95 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder,👍 json-joy/json-pack CborEncoderFast -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 json-joy/json-pack CborEncoderFast x 295,817 ops/sec ±0.61% (98 runs sampled) -👍 json-joy/json-pack CborEncoder x 293,260 ops/sec ±0.37% (97 runs sampled) -👍 cborg x 46,351 ops/sec ±0.46% (99 runs sampled) -👍 cbor-x x 221,037 ops/sec ±0.49% (96 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 json-joy/json-pack CborEncoderFast x 397,191 ops/sec ±1.10% (93 runs sampled) -👍 json-joy/json-pack CborEncoder x 393,080 ops/sec ±0.86% (91 runs sampled) -👍 cborg x 73,491 ops/sec ±0.51% (98 runs sampled) -👍 cbor-x x 386,859 ops/sec ±0.82% (94 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoderFast --------------------------------------------------------------------------- Short strings, 170 bytes -👍 json-joy/json-pack CborEncoderFast x 1,746,092 ops/sec ±0.40% (98 runs sampled) -👍 json-joy/json-pack CborEncoder x 1,745,521 ops/sec ±0.40% (99 runs sampled) -👍 cborg x 198,683 ops/sec ±0.57% (96 runs sampled) -👍 cbor-x x 1,276,409 ops/sec ±0.62% (93 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoderFast,👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 json-joy/json-pack CborEncoderFast x 2,558,939 ops/sec ±0.46% (98 runs sampled) -👍 json-joy/json-pack CborEncoder x 2,575,323 ops/sec ±0.39% (95 runs sampled) -👍 cborg x 230,191 ops/sec ±0.40% (98 runs sampled) -👍 cbor-x x 2,966,610 ops/sec ±0.34% (97 runs sampled) -Fastest is 👍 cbor-x ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 json-joy/json-pack CborEncoderFast x 1,318,484 ops/sec ±0.45% (100 runs sampled) -👍 json-joy/json-pack CborEncoder x 1,332,239 ops/sec ±0.40% (100 runs sampled) -👍 cborg x 168,853 ops/sec ±0.42% (96 runs sampled) -👍 cbor-x x 1,824,744 ops/sec ±0.43% (95 runs sampled) -Fastest is 👍 cbor-x -``` - -### Decoding - -``` -npx ts-node benchmarks/json-pack/bench.cbor.decoding.ts -========================================================================== Benchmark: CBOR Decoding -Warmup: 1000x , Node.js: v20.2.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Combined, 634613 bytes -👍 json-joy/json-pack CborDecoder x 3,869 ops/sec ±0.18% (98 runs sampled) -👎 cbor-x x 3,636 ops/sec ±0.13% (100 runs sampled) -👍 cborg x 1,848 ops/sec ±0.27% (99 runs sampled) -👍 cbor x 313 ops/sec ±0.85% (95 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder ---------------------------------------------------------------------------- Small object, 274 bytes -👍 json-joy/json-pack CborDecoder x 4,547,927 ops/sec ±0.13% (98 runs sampled) -👍 cbor-x x 4,146,745 ops/sec ±0.15% (94 runs sampled) -👍 cborg x 1,979,229 ops/sec ±0.15% (99 runs sampled) -👍 cbor x 133,271 ops/sec ±2.51% (92 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder ------------------------------------------------------------------------- Typical object, 8253 bytes -👍 json-joy/json-pack CborDecoder x 373,571 ops/sec ±0.33% (97 runs sampled) -👍 cbor-x x 254,533 ops/sec ±0.57% (99 runs sampled) -👍 cborg x 121,327 ops/sec ±0.36% (97 runs sampled) -👍 cbor x 19,516 ops/sec ±0.22% (98 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder -------------------------------------------------------------------------- Large object, 34563 bytes -👍 json-joy/json-pack CborDecoder x 108,250 ops/sec ±0.70% (96 runs sampled) -👍 cbor-x x 86,146 ops/sec ±0.32% (101 runs sampled) -👍 cborg x 33,641 ops/sec ±0.56% (93 runs sampled) -👍 cbor x 6,383 ops/sec ±0.58% (97 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder -------------------------------------------------------------------- Very large object, 437014 bytes -👍 json-joy/json-pack CborDecoder x 4,374 ops/sec ±0.31% (94 runs sampled) -👎 cbor-x x 3,943 ops/sec ±0.30% (98 runs sampled) -👍 cborg x 1,685 ops/sec ±0.29% (79 runs sampled) -👍 cbor x 310 ops/sec ±0.15% (89 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder ------------------------------------------------------------------ Object with many keys, 7575 bytes -👍 json-joy/json-pack CborDecoder x 92,625 ops/sec ±0.51% (95 runs sampled) -👎 cbor-x x 91,511 ops/sec ±0.94% (93 runs sampled) -👍 cborg x 54,355 ops/sec ±0.41% (97 runs sampled) -👍 cbor x 13,289 ops/sec ±1.41% (99 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder,👎 cbor-x ------------------------------------------------------------------------- String ladder, 35622 bytes -👍 json-joy/json-pack CborDecoder x 240,683 ops/sec ±0.34% (100 runs sampled) -👍 cbor-x x 324,927 ops/sec ±0.40% (96 runs sampled) -👍 cborg x 70,820 ops/sec ±0.58% (95 runs sampled) -👍 cbor x 24,792 ops/sec ±0.76% (96 runs sampled) -Fastest is 👍 cbor-x -------------------------------------------------------------------------- Long strings, 85228 bytes -👍 json-joy/json-pack CborDecoder x 96,957 ops/sec ±0.50% (98 runs sampled) -👍 cbor-x x 94,397 ops/sec ±0.51% (94 runs sampled) -👍 cborg x 69,925 ops/sec ±6.38% (91 runs sampled) -👍 cbor x 34,779 ops/sec ±10.73% (79 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder -------------------------------------------------------------------------- Short strings, 1211 bytes -👍 json-joy/json-pack CborDecoder x 1,177,079 ops/sec ±0.61% (94 runs sampled) -👍 cbor-x x 1,070,770 ops/sec ±1.19% (90 runs sampled) -👍 cborg x 385,823 ops/sec ±0.79% (94 runs sampled) -👍 cbor x 53,147 ops/sec ±0.91% (91 runs sampled) -Fastest is 👍 json-joy/json-pack CborDecoder -------------------------------------------------------------------------------- Numbers, 1544 bytes -👍 json-joy/json-pack CborDecoder x 974,821 ops/sec ±0.72% (98 runs sampled) -👍 cbor-x x 1,576,220 ops/sec ±0.68% (95 runs sampled) -👍 cborg x 464,996 ops/sec ±0.44% (94 runs sampled) -👍 cbor x 34,161 ops/sec ±0.76% (92 runs sampled) -Fastest is 👍 cbor-x ---------------------------------------------------------------------------------- Tokens, 530 bytes -👍 json-joy/json-pack CborDecoder x 1,198,726 ops/sec ±0.53% (96 runs sampled) -👍 cbor-x x 1,927,307 ops/sec ±0.67% (80 runs sampled) -👍 cborg x 957,531 ops/sec ±0.62% (98 runs sampled) -👍 cbor x 44,276 ops/sec ±10.58% (80 runs sampled) -Fastest is 👍 cbor-x -``` - -### Other - -By writer buffer size: - -``` -npx ts-node benchmarks/json-pack/bench.writer-size.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 Max ----------------------------------------------------------------------------- Small object, 44 bytes -👍 1 MB x 6,313,890 ops/sec ±0.12% (101 runs sampled) -👍 256 KB x 6,289,685 ops/sec ±0.11% (97 runs sampled) -👍 64 KB x 6,275,863 ops/sec ±0.12% (100 runs sampled) -👍 16 KB x 6,254,832 ops/sec ±0.24% (98 runs sampled) -👍 4 KB x 6,187,636 ops/sec ±0.13% (99 runs sampled) -👍 1 KB x 5,890,157 ops/sec ±0.14% (99 runs sampled) -Fastest is 👍 1 MB -------------------------------------------------------------------------- Typical object, 993 bytes -👍 1 MB x 497,752 ops/sec ±0.21% (100 runs sampled) -👍 256 KB x 495,574 ops/sec ±0.15% (99 runs sampled) -👍 64 KB x 494,724 ops/sec ±0.15% (98 runs sampled) -👍 16 KB x 489,579 ops/sec ±0.23% (97 runs sampled) -👍 4 KB x 455,526 ops/sec ±0.34% (98 runs sampled) -👍 1 KB x 433,038 ops/sec ±0.48% (97 runs sampled) -Fastest is 👍 1 MB --------------------------------------------------------------------------- Large object, 3741 bytes -👍 1 MB x 140,580 ops/sec ±0.39% (96 runs sampled) -👍 256 KB x 136,933 ops/sec ±0.39% (92 runs sampled) -👍 64 KB x 139,697 ops/sec ±0.27% (98 runs sampled) -👍 16 KB x 137,278 ops/sec ±0.33% (98 runs sampled) -👍 4 KB x 130,838 ops/sec ±0.19% (98 runs sampled) -👍 1 KB x 122,987 ops/sec ±0.45% (94 runs sampled) -Fastest is 👍 1 MB --------------------------------------------------------------------- Very large object, 45750 bytes -👍 1 MB x 5,883 ops/sec ±0.12% (101 runs sampled) -👍 256 KB x 5,845 ops/sec ±0.66% (91 runs sampled) -👍 64 KB x 5,783 ops/sec ±0.26% (100 runs sampled) -👍 16 KB x 5,584 ops/sec ±0.59% (94 runs sampled) -👍 4 KB x 5,648 ops/sec ±0.35% (98 runs sampled) -👍 1 KB x 5,649 ops/sec ±0.35% (95 runs sampled) -Fastest is 👍 1 MB,👍 256 KB ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 1 MB x 282,535 ops/sec ±0.34% (98 runs sampled) -👍 256 KB x 282,055 ops/sec ±0.34% (95 runs sampled) -👍 64 KB x 286,786 ops/sec ±0.22% (97 runs sampled) -👍 16 KB x 283,067 ops/sec ±0.27% (97 runs sampled) -👍 4 KB x 281,647 ops/sec ±0.24% (100 runs sampled) -👍 1 KB x 259,775 ops/sec ±0.33% (96 runs sampled) -Fastest is 👍 64 KB -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 1 MB x 308,326 ops/sec ±0.23% (96 runs sampled) -👍 256 KB x 307,324 ops/sec ±0.34% (100 runs sampled) -👍 64 KB x 305,368 ops/sec ±0.23% (97 runs sampled) -👍 16 KB x 289,570 ops/sec ±0.46% (99 runs sampled) -👍 4 KB x 270,486 ops/sec ±0.52% (96 runs sampled) -👍 1 KB x 211,091 ops/sec ±0.57% (95 runs sampled) -Fastest is 👍 1 MB,👍 256 KB --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 1 MB x 446,622 ops/sec ±0.48% (98 runs sampled) -👍 256 KB x 438,083 ops/sec ±0.58% (94 runs sampled) -👍 64 KB x 421,277 ops/sec ±0.50% (97 runs sampled) -👍 16 KB x 349,768 ops/sec ±1.32% (93 runs sampled) -👍 4 KB x 350,886 ops/sec ±0.76% (92 runs sampled) -👍 1 KB x 348,879 ops/sec ±1.00% (92 runs sampled) -Fastest is 👍 1 MB --------------------------------------------------------------------------- Short strings, 170 bytes -👍 1 MB x 2,003,291 ops/sec ±0.18% (99 runs sampled) -👍 256 KB x 2,002,815 ops/sec ±0.30% (98 runs sampled) -👍 64 KB x 2,003,416 ops/sec ±0.22% (98 runs sampled) -👍 16 KB x 1,973,326 ops/sec ±0.31% (96 runs sampled) -👍 4 KB x 1,938,991 ops/sec ±0.28% (98 runs sampled) -👍 1 KB x 1,815,441 ops/sec ±0.24% (99 runs sampled) -Fastest is 👍 1 MB,👍 64 KB,👍 256 KB --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 1 MB x 3,301,798 ops/sec ±0.25% (99 runs sampled) -👍 256 KB x 3,284,645 ops/sec ±0.30% (98 runs sampled) -👍 64 KB x 3,272,060 ops/sec ±0.94% (96 runs sampled) -👍 16 KB x 3,317,569 ops/sec ±0.25% (98 runs sampled) -👍 4 KB x 3,238,186 ops/sec ±0.34% (96 runs sampled) -👍 1 KB x 3,017,336 ops/sec ±0.68% (98 runs sampled) -Fastest is 👍 16 KB ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 1 MB x 1,698,059 ops/sec ±0.24% (101 runs sampled) -👍 256 KB x 1,644,210 ops/sec ±0.70% (99 runs sampled) -👍 64 KB x 1,680,855 ops/sec ±0.22% (97 runs sampled) -👍 16 KB x 1,651,801 ops/sec ±0.35% (97 runs sampled) -👍 4 KB x 1,634,786 ops/sec ±0.72% (95 runs sampled) -👍 1 KB x 1,633,724 ops/sec ±0.25% (98 runs sampled) -Fastest is 👍 1 MB -``` - -Buffer vs Slice results: - -``` -npx ts-node benchmarks/json-pack/bench.slice.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 Max ----------------------------------------------------------------------------- Small object, 44 bytes -👍 Uint8Array x 6,375,191 ops/sec ±0.29% (99 runs sampled) -👎 Slice x 7,477,318 ops/sec ±0.24% (99 runs sampled) -Fastest is 👎 Slice -------------------------------------------------------------------------- Typical object, 993 bytes -👍 Uint8Array x 481,245 ops/sec ±0.27% (95 runs sampled) -👎 Slice x 487,881 ops/sec ±0.24% (95 runs sampled) -Fastest is 👎 Slice --------------------------------------------------------------------------- Large object, 3741 bytes -👍 Uint8Array x 139,034 ops/sec ±0.28% (99 runs sampled) -👎 Slice x 139,084 ops/sec ±0.30% (93 runs sampled) -Fastest is 👎 Slice,👍 Uint8Array --------------------------------------------------------------------- Very large object, 45750 bytes -👍 Uint8Array x 5,992 ops/sec ±0.17% (98 runs sampled) -👎 Slice x 5,973 ops/sec ±0.18% (101 runs sampled) -Fastest is 👍 Uint8Array ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 Uint8Array x 283,511 ops/sec ±0.21% (96 runs sampled) -👎 Slice x 284,962 ops/sec ±0.20% (100 runs sampled) -Fastest is 👎 Slice -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 Uint8Array x 321,418 ops/sec ±0.36% (97 runs sampled) -👎 Slice x 324,213 ops/sec ±0.34% (99 runs sampled) -Fastest is 👎 Slice --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 Uint8Array x 417,711 ops/sec ±0.72% (94 runs sampled) -👎 Slice x 421,504 ops/sec ±0.72% (94 runs sampled) -Fastest is 👎 Slice --------------------------------------------------------------------------- Short strings, 170 bytes -👍 Uint8Array x 2,186,736 ops/sec ±0.21% (97 runs sampled) -👎 Slice x 2,283,908 ops/sec ±0.26% (98 runs sampled) -Fastest is 👎 Slice --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 Uint8Array x 3,305,268 ops/sec ±0.21% (100 runs sampled) -👎 Slice x 3,526,413 ops/sec ±0.32% (97 runs sampled) -Fastest is 👎 Slice ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 Uint8Array x 1,681,882 ops/sec ±0.14% (100 runs sampled) -👎 Slice x 1,721,419 ops/sec ±0.35% (97 runs sampled) -Fastest is 👎 Slice -``` - -### DAG-CBOR benchmarks - -``` -npx ts-node benchmarks/json-pack/bench.cbor-dag.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.4.0 , Arch: arm64 , CPU: Apple M1 ------------------------------------------------------------------------------ Combined, 63365 bytes -👍 json-joy/json-pack CborEncoder x 4,802 ops/sec ±0.29% (99 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 3,747 ops/sec ±0.15% (99 runs sampled) -👍 cborg x 494 ops/sec ±2.66% (74 runs sampled) -👍 cbor-x x 4,119 ops/sec ±0.29% (98 runs sampled) -👎 Buffer.from(JSON.stringify) x 3,069 ops/sec ±0.13% (101 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder ----------------------------------------------------------------------------- Small object, 44 bytes -👍 json-joy/json-pack CborEncoder x 5,373,104 ops/sec ±0.64% (98 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 5,046,824 ops/sec ±0.37% (95 runs sampled) -👍 cborg x 444,568 ops/sec ±3.20% (85 runs sampled) -👍 cbor-x x 3,876,636 ops/sec ±0.54% (94 runs sampled) -👎 Buffer.from(JSON.stringify) x 2,419,844 ops/sec ±0.13% (97 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -👍 json-joy/json-pack CborEncoder x 444,693 ops/sec ±0.24% (98 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 395,237 ops/sec ±0.55% (98 runs sampled) -👍 cborg x 38,173 ops/sec ±2.96% (89 runs sampled) -👍 cbor-x x 369,911 ops/sec ±0.20% (97 runs sampled) -👎 Buffer.from(JSON.stringify) x 209,177 ops/sec ±0.14% (99 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -👍 json-joy/json-pack CborEncoder x 129,963 ops/sec ±0.15% (98 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 116,481 ops/sec ±0.40% (97 runs sampled) -👍 cborg x 11,650 ops/sec ±2.91% (86 runs sampled) -👍 cbor-x x 102,557 ops/sec ±0.21% (96 runs sampled) -👎 Buffer.from(JSON.stringify) x 63,205 ops/sec ±0.11% (102 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------- Very large object, 45750 bytes -👍 json-joy/json-pack CborEncoder x 5,532 ops/sec ±0.20% (99 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 4,209 ops/sec ±0.48% (99 runs sampled) -👍 cborg x 563 ops/sec ±2.88% (72 runs sampled) -👍 cbor-x x 4,767 ops/sec ±0.28% (99 runs sampled) -👎 Buffer.from(JSON.stringify) x 6,769 ops/sec ±0.19% (98 runs sampled) -Fastest is 👎 Buffer.from(JSON.stringify) ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 json-joy/json-pack CborEncoder x 263,890 ops/sec ±0.26% (97 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 180,107 ops/sec ±0.26% (98 runs sampled) -👍 cborg x 25,011 ops/sec ±2.62% (91 runs sampled) -👍 cbor-x x 195,063 ops/sec ±0.30% (97 runs sampled) -👎 Buffer.from(JSON.stringify) x 192,690 ops/sec ±0.19% (96 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder -------------------------------------------------------------------------- String ladder, 4037 bytes -👍 json-joy/json-pack CborEncoder x 204,028 ops/sec ±0.20% (101 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 187,891 ops/sec ±0.18% (97 runs sampled) -👍 cborg x 30,417 ops/sec ±3.11% (90 runs sampled) -👍 cbor-x x 158,968 ops/sec ±0.40% (100 runs sampled) -👎 Buffer.from(JSON.stringify) x 56,748 ops/sec ±0.09% (99 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 json-joy/json-pack CborEncoder x 407,500 ops/sec ±0.21% (97 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 398,762 ops/sec ±0.25% (98 runs sampled) -👍 cborg x 86,854 ops/sec ±2.66% (81 runs sampled) -👍 cbor-x x 398,117 ops/sec ±0.62% (98 runs sampled) -👎 Buffer.from(JSON.stringify) x 28,748 ops/sec ±0.40% (100 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -👍 json-joy/json-pack CborEncoder x 2,022,274 ops/sec ±0.15% (100 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 1,543,637 ops/sec ±0.16% (99 runs sampled) -👍 cborg x 168,393 ops/sec ±2.98% (88 runs sampled) -👍 cbor-x x 1,348,931 ops/sec ±0.51% (100 runs sampled) -👎 Buffer.from(JSON.stringify) x 1,005,204 ops/sec ±0.45% (99 runs sampled) -Fastest is 👍 json-joy/json-pack CborEncoder --------------------------------------------------------------------------------- Numbers, 331 bytes -👍 json-joy/json-pack CborEncoder x 1,290,404 ops/sec ±0.15% (99 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 1,293,654 ops/sec ±0.12% (101 runs sampled) -👍 cborg x 117,671 ops/sec ±2.12% (92 runs sampled) -👍 cbor-x x 1,547,093 ops/sec ±0.19% (99 runs sampled) -👎 Buffer.from(JSON.stringify) x 677,253 ops/sec ±0.14% (99 runs sampled) -Fastest is 👍 cbor-x ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 json-joy/json-pack CborEncoder x 1,525,319 ops/sec ±0.37% (99 runs sampled) -👍 json-joy/json-pack CborEncoderDag x 1,509,373 ops/sec ±0.20% (98 runs sampled) -👍 cborg x 225,699 ops/sec ±1.00% (96 runs sampled) -👍 cbor-x x 1,980,475 ops/sec ±0.18% (99 runs sampled) -👎 Buffer.from(JSON.stringify) x 1,074,160 ops/sec ±0.15% (97 runs sampled) -Fastest is 👍 cbor-x -``` diff --git a/src/json-pack/cbor/__tests__/CborDecoder.readLevel.spec.ts b/src/json-pack/cbor/__tests__/CborDecoder.readLevel.spec.ts deleted file mode 100644 index 4a6e7d17f6..0000000000 --- a/src/json-pack/cbor/__tests__/CborDecoder.readLevel.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; -import {JsonPackValue} from '../../JsonPackValue'; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); - -test('decodes a primitive as is', () => { - const encoded = encoder.encode(1.1); - const decoded = decoder.decodeLevel(encoded); - expect(decoded).toBe(1.1); -}); - -test('decodes object with one level of values', () => { - const value = { - foo: 'bar', - baz: true, - }; - const encoded = encoder.encode(value); - const decoded = decoder.decodeLevel(encoded); - expect(decoded).toStrictEqual(value); -}); - -test('decodes nested objects and arrays as JsonPackValue, in object', () => { - const value = { - foo: 'bar', - baz: true, - arr: [1, 2, 3], - obj: { - a: 'b', - }, - }; - const encoded = encoder.encode(value); - const decoded = decoder.decodeLevel(encoded); - expect(decoded).toMatchObject({ - foo: 'bar', - baz: true, - arr: expect.any(JsonPackValue), - obj: expect.any(JsonPackValue), - }); - const arr = decoder.decode((decoded as any).arr.val); - expect(arr).toStrictEqual([1, 2, 3]); - const obj = decoder.decode((decoded as any).obj.val); - expect(obj).toStrictEqual({ - a: 'b', - }); -}); - -test('decodes array with one level of values', () => { - const value = [1, 'foo', true]; - const encoded = encoder.encode(value); - const decoded = decoder.decodeLevel(encoded); - expect(decoded).toStrictEqual(value); -}); - -test('decodes nested objects and arrays as JsonPackValue, in array', () => { - const value = [ - 1, - 'foo', - true, - [1, 2, 3], - { - a: 'b', - }, - ]; - const encoded = encoder.encode(value); - const decoded = decoder.decodeLevel(encoded); - expect(decoded).toMatchObject([1, 'foo', true, expect.any(JsonPackValue), expect.any(JsonPackValue)]); - const arr = decoder.decode((decoded as any)[3].val); - expect(arr).toStrictEqual([1, 2, 3]); - const obj = decoder.decode((decoded as any)[4].val); - expect(obj).toStrictEqual({ - a: 'b', - }); -}); diff --git a/src/json-pack/cbor/__tests__/CborDecoder.shallow-reading.spec.ts b/src/json-pack/cbor/__tests__/CborDecoder.shallow-reading.spec.ts deleted file mode 100644 index bc90ba2ce5..0000000000 --- a/src/json-pack/cbor/__tests__/CborDecoder.shallow-reading.spec.ts +++ /dev/null @@ -1,183 +0,0 @@ -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); - -describe('shallow reading values, without parsing the document', () => { - describe('reading object header', () => { - test('can read object size of empty oject', () => { - const encoded = encoder.encode({}); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(0); - }); - - test('can read small object size', () => { - const encoded = encoder.encode({foo: 'bar', a: 1, b: 2}); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(3); - }); - - test('medium size object size', () => { - const encoded = encoder.encode({ - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - }); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(17); - }); - - test('throws if value is not an object', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - expect(() => decoder.readObjHdr()).toThrowError(); - }); - }); - - describe('object key finding', () => { - test('can find object key', () => { - const encoded = encoder.encode({foo: 'bar'}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('foo').val(); - expect(decoded).toBe('bar'); - }); - - test('can find object key in the middle of the object', () => { - const encoded = encoder.encode({x: 123, y: 0, z: -1}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('y').val(); - expect(decoded).toBe(0); - }); - - test('can find object key at the end of the object', () => { - const encoded = encoder.encode({x: 123, y: 0, z: -1}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('z').val(); - expect(decoded).toBe(-1); - }); - }); - - describe('reading array header', () => { - test('can read array size of an empty array', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(0); - }); - - test('can read small array size', () => { - const encoded = encoder.encode(['bar', 1, 2]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(3); - }); - - test('medium size array size', () => { - const encoded = encoder.encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(17); - }); - - test('throws if value is not an array', () => { - const encoded = encoder.encode({}); - decoder.reader.reset(encoded); - expect(() => decoder.readArrHdr()).toThrowError(); - }); - }); - - describe('array index finding', () => { - test('can find value at beginning of array', () => { - const encoded = encoder.encode(['foobar']); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(0).val(); - expect(decoded).toBe('foobar'); - }); - - test('can find value in the middle of array', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(1).val(); - expect(decoded).toBe(2); - }); - - test('can find value at the end of array', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(2).val(); - expect(decoded).toBe(3); - }); - - test('throws if array index is out of bounds', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - expect(() => decoder.findIndex(3).val()).toThrowError(); - }); - - test('throws when reading value from an empty array', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - expect(() => decoder.findIndex(0).val()).toThrowError(); - }); - }); - - const doc = { - a: { - b: { - c: { - d: { - e: [1, 2, 3], - }, - hmm: [ - { - foo: 'bar', - }, - ], - }, - }, - }, - }; - - test('can shallow read a deeply nested value', () => { - const encoded = encoder.encode(doc); - - decoder.reader.reset(encoded); - const decoded1 = decoder.findKey('a').findKey('b').findKey('c').findKey('d').findKey('e').val(); - expect(decoded1).toStrictEqual([1, 2, 3]); - - decoder.reader.reset(encoded); - const decoded2 = decoder.findKey('a').findKey('b').findKey('c').findKey('d').findKey('e').findIndex(1).val(); - expect(decoded2).toBe(2); - - decoder.reader.reset(encoded); - const decoded3 = decoder.findKey('a').findKey('b').findKey('c').findKey('hmm').findIndex(0).findKey('foo').val(); - expect(decoded3).toBe('bar'); - }); - - describe('.find()', () => { - test('can find deeply nested value', () => { - const encoded = encoder.encode(doc); - decoder.reader.reset(encoded); - const decoded1 = decoder.find(['a', 'b', 'c', 'd', 'e', 1]).val(); - expect(decoded1).toStrictEqual(2); - }); - }); -}); diff --git a/src/json-pack/cbor/__tests__/CborDecoder.spec.ts b/src/json-pack/cbor/__tests__/CborDecoder.spec.ts deleted file mode 100644 index b525723e35..0000000000 --- a/src/json-pack/cbor/__tests__/CborDecoder.spec.ts +++ /dev/null @@ -1,408 +0,0 @@ -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; -import {JsonPackExtension} from '../../JsonPackExtension'; -import {JsonPackValue} from '../../JsonPackValue'; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); - -describe('unsigned integer', () => { - const uints: (number | bigint)[] = [ - 0, - 6, - 23, - 24, - 25, - 55, - 111, - 166, - 200, - 222, - 255, - 256, - 444, - 1111, - 22222, - 55555, - 0xffff, - 0x10000, - 0xffffff, - 0xffffff, - 0xfffffff, - 0xffffffff, - 0x100000000, - 0xfffffffffffff, - 0x1fffffffffffff, - BigInt('0x1ffffffffffffff'), - BigInt('0x1ffffffffffffffA'), - ]; - - for (const num of uints) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - const decoded = decoder.decode(encoded); - expect(decoded).toBe(num); - }); - } -}); - -describe('signed integer', () => { - const ints: (number | bigint)[] = [ - -1, - -2, - -4, - -16, - -23, - -24, - -26, - -123, - -4444, - -44444, - -66666, - -33333333, - -0xffff, - -0x10000, - -0xffffff, - -0xffffff, - -0xfffffff, - -0xffffffff, - -0x100000000, - -0xfffffffffffff, - -0x1fffffffffffff, - BigInt('-12312312312312312232'), - ]; - - for (const num of ints) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - const decoded = decoder.decode(encoded); - expect(decoded).toBe(num); - }); - } -}); - -describe('binary', () => { - const toUint8Array = (buf: Buffer): Uint8Array => { - const uint8 = new Uint8Array(buf.length); - buf.copy(uint8); - return uint8; - }; - - const buffers: Uint8Array[] = [ - new Uint8Array([]), - new Uint8Array([0]), - new Uint8Array([1, 2, 3]), - new Uint8Array([1, 2, 3, 4, 5]), - toUint8Array(Buffer.alloc(1)), - toUint8Array(Buffer.alloc(15)), - toUint8Array(Buffer.alloc(23)), - toUint8Array(Buffer.alloc(24)), - toUint8Array(Buffer.alloc(25)), - toUint8Array(Buffer.alloc(123)), - toUint8Array(Buffer.alloc(255)), - toUint8Array(Buffer.alloc(256, 2)), - toUint8Array(Buffer.alloc(1024, 3)), - toUint8Array(Buffer.alloc(66666, 5)), - ]; - - for (const val of buffers) { - test(`${String(val).substring(0, 80)}`, () => { - const encoded = encoder.encode(val); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual(val); - }); - } - - test('indefinite length binary', () => { - encoder.writer.reset(); - encoder.writeStartBin(); - encoder.writeBin(new Uint8Array([1, 2, 3])); - encoder.writeBin(new Uint8Array([4, 5, 6])); - encoder.writeBin(new Uint8Array([7, 8, 9])); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9])); - }); -}); - -describe('strings', () => { - const strings: string[] = [ - '', - 'a', - 'b', - '👍', - 'asdf', - 'asdfa adsf asdf a', - 'as 👍 df', - 'asdf asfd asdf asdf as', - 'asdf asfd 😱 asdf asdf 👀 as', - 'asdf asfasdfasdf asdf asdf d 😱 asdf asdfasdf asdf asdf asdf asdf asdfasdf asdf asdfasdfasdf asdf asdf asdfasdf asdf asdf asdf asdf asdfasdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asfd asdf asdf asdf sdf asdf asdf 👀 as', - ]; - - for (const num of strings) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - const decoded = decoder.decode(encoded); - expect(decoded).toBe(num); - }); - } - - test('indefinite length string', () => { - encoder.writer.reset(); - encoder.writeStartStr(); - encoder.writeStr('abc'); - encoder.writeStr('def'); - encoder.writeStr('ghi'); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual('abcdefghi'); - }); -}); - -describe('arrays', () => { - const arrays: unknown[][] = [ - [], - [0], - [1, 2, 3], - ['qwerty'], - [1, 'a', -2], - [1, 'a', -2, 'qwerty'], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], - [[]], - [[1, 2, 3]], - [[[[[[[[]]]]]]]], - JSON.parse('['.repeat(20) + ']'.repeat(20)), - JSON.parse('['.repeat(50) + ']'.repeat(50)), - JSON.parse('[' + '1,'.repeat(50) + '2]'), - JSON.parse('[' + '1,'.repeat(150) + '2]'), - JSON.parse('[' + '1,'.repeat(250) + '2]'), - JSON.parse('[' + '1,'.repeat(350) + '2]'), - JSON.parse('[' + '1,'.repeat(1250) + '2]'), - JSON.parse('[' + '1,'.repeat(55250) + '2]'), - JSON.parse('[' + '1,'.repeat(77250) + '2]'), - ]; - - for (const val of arrays) { - test(`${JSON.stringify(val).substring(0, 80)} (${val.length})`, () => { - const encoded = encoder.encode(val); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual(val); - }); - } - - test('indefinite length array', () => { - encoder.writer.reset(); - encoder.writeStartArr(); - encoder.writeArr([1, 2, 3]); - encoder.writeArr([4, 5, 6]); - encoder.writeArr([7, 8, 9]); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual([ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9], - ]); - }); -}); - -describe('objects', () => { - const objects: Record[] = [ - {}, - {a: 'b'}, - {foo: 'bar'}, - {foo: 123}, - {foo: {}}, - {foo: {bar: {}}}, - {foo: {bar: {baz: {}}}}, - {foo: {bar: {baz: {quz: 'qux'}}}}, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - }, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - 23: 23, - }, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - 23: 23, - 24: 24, - }, - ]; - - for (const val of objects) { - test(`${JSON.stringify(val).substring(0, 80)} (${Object.keys(val).length})`, () => { - const encoded = encoder.encode(val); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual(val); - }); - } - - test('indefinite length object', () => { - encoder.writer.reset(); - encoder.writeStartMap(); - encoder.writeAny('foo'); - encoder.writeAny(123); - encoder.writeAny('bar'); - encoder.writeAny(4); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual({foo: 123, bar: 4}); - }); -}); - -describe('tags', () => { - const testTag = (tag: number, value: unknown) => { - test(`can encode a tag = ${tag}, value = ${value}`, () => { - encoder.writer.reset(); - encoder.writeTag(9, 123); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded) as JsonPackExtension; - expect(decoded.tag).toBe(9); - expect(decoded.val).toBe(123); - }); - }; - - testTag(1, 1); - testTag(5, []); - testTag(23, 'adsf'); - testTag(24, 'adsf asdf'); - testTag(125, {}); - testTag(1256, {foo: 'bar'}); - testTag(0xfffff, {foo: 'bar'}); - testTag(0xffffff, {foo: 'bar'}); - testTag(0xfffffffff, {foo: 'bar'}); -}); - -describe('tokens (simple values)', () => { - const testToken = (token: number) => { - test(`can encode a token = ${token}`, () => { - encoder.writer.reset(); - encoder.writeTkn(token); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded) as JsonPackValue; - expect(decoded.val).toBe(token); - }); - }; - - for (let i = 0; i <= 19; i++) testToken(i); - - const testNativeToken = (token: number, expected: unknown) => { - test(`can encode a token = ${token}`, () => { - encoder.writer.reset(); - encoder.writeTkn(token); - const encoded = encoder.writer.flush(); - const decoded = decoder.decode(encoded) as JsonPackValue; - expect(decoded).toBe(expected); - }); - }; - - testNativeToken(20, false); - testNativeToken(21, true); - testNativeToken(22, null); - testNativeToken(23, undefined); - - const testJsTokens = (token: unknown) => { - test(`can encode a token = ${token}`, () => { - const encoded = encoder.encode(token); - const decoded = decoder.decode(encoded); - expect(decoded).toBe(token); - }); - }; - - testJsTokens(false); - testJsTokens(true); - testJsTokens(null); - testJsTokens(undefined); -}); - -describe('maps', () => { - const maps: Map[] = [ - new Map(), - new Map([['foo', 'bar']]), - new Map([ - ['foo', 'bar'], - [1, 2], - [true, false], - [null, null], - ]), - ]; - - for (const map of maps) { - test(`{${[...map.entries()]}}`, () => { - const encoded = encoder.encode(map); - decoder.reader.reset(encoded); - const decoded = decoder.readAsMap(); - expect(decoded).toStrictEqual(map); - }); - } -}); diff --git a/src/json-pack/cbor/__tests__/CborDecoder.validate.spec.ts b/src/json-pack/cbor/__tests__/CborDecoder.validate.spec.ts deleted file mode 100644 index a07015fee0..0000000000 --- a/src/json-pack/cbor/__tests__/CborDecoder.validate.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); - -test('value is too short, buffer too long', () => { - const encoded = encoder.encode(1.1); - decoder.validate(encoded); - const corrupted = new Uint8Array(encoded.length + 1); - corrupted.set(encoded); - expect(() => decoder.validate(corrupted)).toThrow(); -}); - -test('value is truncated, buffer too short', () => { - const encoded = encoder.encode(1.1); - decoder.validate(encoded); - const corrupted = encoded.subarray(0, encoded.length - 1); - expect(() => decoder.validate(corrupted)).toThrow(); -}); - -test('validates valid indefinite map', () => { - encoder.writer.reset(); - encoder.writeStartMap(); - encoder.writeStr('foo'); - encoder.writeStr('bar'); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - decoder.validate(encoded); -}); - -test('value contents is corrupted, break between map key and value', () => { - encoder.writer.reset(); - encoder.writeStartMap(); - encoder.writeStr('foo'); - encoder.writeEnd(); - encoder.writeStr('bar'); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - expect(() => decoder.validate(encoded)).toThrow(); -}); - -test('value contents is corrupted, no value in indefinite map', () => { - encoder.writer.reset(); - encoder.writeStartMap(); - encoder.writeStr('foo'); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - expect(() => decoder.validate(encoded)).toThrow(); -}); - -test('invalid value', () => { - const encoded = new Uint8Array([0xff]); - expect(() => decoder.validate(encoded)).toThrow(); -}); diff --git a/src/json-pack/cbor/__tests__/CborDecoderDag.spec.ts b/src/json-pack/cbor/__tests__/CborDecoderDag.spec.ts deleted file mode 100644 index 9266aac553..0000000000 --- a/src/json-pack/cbor/__tests__/CborDecoderDag.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {CborEncoderStable} from '../CborEncoderStable'; -import {CborDecoderDag} from '../CborDecoderDag'; -import {JsonPackExtension} from '../../JsonPackExtension'; - -const writer = new Writer(1); -const encoder = new CborEncoderStable(writer); -const decoder = new CborDecoderDag(); - -describe('only extension = 42 is permitted', () => { - test('can decode a value with extension 42', () => { - const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(42, 'b')}); - const val = decoder.read(encoded); - expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - }); - - test('non-42 extensions are not processed', () => { - const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(43, 'b')}); - const val = decoder.read(encoded); - expect(val).toStrictEqual({a: 'a', b: 'b'}); - }); - - // test('can encode CID using inlined custom class', () => { - // class CID { - // constructor(public readonly value: string) {} - // } - // const encoder = new CborEncoderDag(writer); - // encoder.writeUnknown = (val: unknown): void => { - // if (val instanceof CID) encoder.writeTag(42, val.value); - // else throw new Error('Unknown value type'); - // }; - // const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(42, 'b')}); - // const val = decoder.read(encoded); - // expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - // const encoded2 = encoder.encode({a: 'a', b: new CID('b')}); - // const val2 = decoder.read(encoded2); - // expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - // }); - - // test('can throw on unknown custom class', () => { - // class CID { - // constructor(public readonly value: string) {} - // } - // class NotCID { - // constructor(public readonly value: string) {} - // } - // const encoder = new CborEncoderDag(writer); - // encoder.writeUnknown = (val: unknown): void => { - // if (val instanceof CID) encoder.writeTag(42, val.value); - // else throw new Error('Unknown value type'); - // }; - // const encoded1 = encoder.encode({a: 'a', b: new CID('b')}); - // expect(() => encoder.encode({a: 'a', b: new NotCID('b')})).toThrowError(new Error('Unknown value type')); - // }); -}); diff --git a/src/json-pack/cbor/__tests__/CborEncoder.spec.ts b/src/json-pack/cbor/__tests__/CborEncoder.spec.ts deleted file mode 100644 index fd98461b9b..0000000000 --- a/src/json-pack/cbor/__tests__/CborEncoder.spec.ts +++ /dev/null @@ -1,413 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonPackValue} from '../../JsonPackValue'; -import {CborEncoder} from '../CborEncoder'; -import {decode} from 'cbor'; - -const writer = new Writer(1); -const encoder = new CborEncoder(writer); - -describe('unsigned integer', () => { - const uints: (number | bigint)[] = [ - 0, - 6, - 23, - 24, - 25, - 55, - 111, - 166, - 200, - 222, - 255, - 256, - 444, - 1111, - 22222, - 55555, - 0xffff, - 0x10000, - 0xffffff, - 0xffffff, - 0xfffffff, - 0xffffffff, - 0x100000000, - 0xfffffffffffff, - 0x1fffffffffffff, - BigInt('0x1ffffffffffffff'), - BigInt('0x1ffffffffffffffA'), - ]; - - for (const num of uints) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - expect(decode(encoded)).toBe(num); - }); - } -}); - -describe('signed integer', () => { - const ints: (number | bigint)[] = [ - -1, - -2, - -4, - -16, - -23, - -24, - -26, - -123, - -4444, - -44444, - -66666, - -33333333, - -0xffff, - -0x10000, - -0xffffff, - -0xffffff, - -0xfffffff, - -0xffffffff, - -0x100000000, - -0xfffffffffffff, - -0x1fffffffffffff, - BigInt('-12312312312312312232'), - ]; - - for (const num of ints) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - expect(decode(encoded)).toBe(num); - }); - } -}); - -describe('floats', () => { - const floats: (number | bigint)[] = [0, 1, 0.0, 0.1, 123.4, 7.34, -123.123]; - - for (const num of floats) { - test(`${num}`, () => { - const encoded = encoder.encode(num); - expect(decode(encoded)).toBe(num); - }); - } -}); - -const toUint8Array = (buf: Buffer): Uint8Array => { - const uint8 = new Uint8Array(buf.length); - buf.copy(uint8); - return uint8; -}; - -describe('binary', () => { - const buffers: Uint8Array[] = [ - new Uint8Array([]), - new Uint8Array([0]), - new Uint8Array([1, 2, 3]), - new Uint8Array([1, 2, 3, 4, 5]), - toUint8Array(Buffer.alloc(1)), - toUint8Array(Buffer.alloc(15)), - toUint8Array(Buffer.alloc(23)), - toUint8Array(Buffer.alloc(24)), - toUint8Array(Buffer.alloc(25)), - toUint8Array(Buffer.alloc(123)), - toUint8Array(Buffer.alloc(255)), - toUint8Array(Buffer.alloc(256, 2)), - toUint8Array(Buffer.alloc(1024, 3)), - toUint8Array(Buffer.alloc(66666, 5)), - ]; - - for (const val of buffers) { - test(`${String(val).substring(0, 80)}`, () => { - const encoded = encoder.encode(val); - const decoded = decode(encoded) as Buffer; - const uint8 = new Uint8Array(decoded.length); - decoded.copy(uint8); - expect(uint8).toStrictEqual(val); - }); - } - - test('indefinite length binary', () => { - encoder.writer.reset(); - encoder.writeStartBin(); - encoder.writeBin(new Uint8Array([1, 2, 3])); - encoder.writeBin(new Uint8Array([4, 5, 6])); - encoder.writeBin(new Uint8Array([7, 8, 9])); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded) as Buffer; - expect(toUint8Array(decoded)).toStrictEqual(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9])); - }); -}); - -describe('strings', () => { - const strings: string[] = [ - '', - 'a', - 'b', - '👍', - 'asdf', - 'asdfa adsf asdf a', - 'as 👍 df', - 'asdf asfd asdf asdf as', - 'asdf asfd 😱 asdf asdf 👀 as', - 'asdf asfasdfasdf asdf asdf d 😱 asdf asdfasdf asdf asdf asdf asdf asdfasdf asdf asdfasdfasdf asdf asdf asdfasdf asdf asdf asdf asdf asdfasdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asfd asdf asdf asdf sdf asdf asdf 👀 as', - ]; - - for (const val of strings) { - test(`${JSON.stringify(val.substring(0, 80))} (${val.length})`, () => { - const encoded = encoder.encode(val); - expect(decode(encoded)).toBe(val); - }); - } - - test('indefinite length string', () => { - encoder.writeStartStr(); - encoder.writeStr('abc'); - encoder.writeStr('def'); - encoder.writeStr('ghi'); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded).toStrictEqual('abcdefghi'); - encoder.writeStartStr(); - encoder.writeStr('abc'); - encoder.writeStr('def'); - encoder.writeStr('ghi'); - encoder.writeEnd(); - const encoded2 = encoder.writer.flush(); - const decoded2 = decode(encoded2); - expect(decoded2).toStrictEqual('abcdefghi'); - }); -}); - -describe('arrays', () => { - const arrays: unknown[][] = [ - [], - [0], - [1, 2, 3], - ['qwerty'], - [1, 'a', -2], - [1, 'a', -2, 'qwerty'], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], - [[]], - [[1, 2, 3]], - [[[[[[[[]]]]]]]], - JSON.parse('['.repeat(20) + ']'.repeat(20)), - JSON.parse('['.repeat(50) + ']'.repeat(50)), - JSON.parse('[' + '1,'.repeat(50) + '2]'), - JSON.parse('[' + '1,'.repeat(150) + '2]'), - JSON.parse('[' + '1,'.repeat(250) + '2]'), - JSON.parse('[' + '1,'.repeat(350) + '2]'), - JSON.parse('[' + '1,'.repeat(1250) + '2]'), - JSON.parse('[' + '1,'.repeat(55250) + '2]'), - JSON.parse('[' + '1,'.repeat(77250) + '2]'), - ]; - - for (const val of arrays) { - test(`${JSON.stringify(val).substring(0, 80)} (${val.length})`, () => { - const encoded = encoder.encode(val); - expect(decode(encoded)).toStrictEqual(val); - }); - - test('indefinite length array', () => { - encoder.writer.reset(); - encoder.writeStartArr(); - encoder.writeArr([1, 2, 3]); - encoder.writeArr([4, 5, 6]); - encoder.writeArr([7, 8, 9]); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded).toStrictEqual([ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9], - ]); - }); - } -}); - -describe('objects', () => { - const objects: Record[] = [ - {}, - {a: 'b'}, - {foo: 'bar'}, - {foo: 123}, - {foo: {}}, - {foo: {bar: {}}}, - {foo: {bar: {baz: {}}}}, - {foo: {bar: {baz: {quz: 'qux'}}}}, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - }, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - 23: 23, - }, - { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19, - 20: 20, - 21: 21, - 22: 22, - 23: 23, - 24: 24, - }, - ]; - - for (const val of objects) { - test(`${JSON.stringify(val).substring(0, 80)} (${Object.keys(val).length})`, () => { - const encoded = encoder.encode(val); - expect(decode(encoded)).toStrictEqual(val); - }); - } - - test('indefinite length object', () => { - encoder.writer.reset(); - encoder.writeStartMap(); - encoder.writeAny('foo'); - encoder.writeAny(123); - encoder.writeAny('bar'); - encoder.writeAny(4); - encoder.writeEnd(); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded).toStrictEqual({foo: 123, bar: 4}); - }); -}); - -describe('tags', () => { - const testTag = (tag: number, value: unknown) => { - test(`can encode a tag = ${tag}, value = ${value}`, () => { - encoder.writer.reset(); - encoder.writeTag(9, 123); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded.tag).toBe(9); - expect(decoded.value).toBe(123); - }); - }; - - testTag(1, 1); - testTag(5, []); - testTag(23, 'adsf'); - testTag(24, 'adsf asdf'); - testTag(125, {}); - testTag(1256, {foo: 'bar'}); - testTag(0xfffff, {foo: 'bar'}); - testTag(0xffffff, {foo: 'bar'}); - testTag(0xfffffffff, {foo: 'bar'}); -}); - -describe('tokens (simple values)', () => { - const testToken = (token: number) => { - test(`can encode a token = ${token}`, () => { - encoder.writer.reset(); - encoder.writeTkn(token); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded.value).toBe(token); - }); - }; - - for (let i = 0; i <= 19; i++) testToken(i); - - const testNativeToken = (token: number, expected: unknown) => { - test(`can encode a token = ${token}`, () => { - encoder.writer.reset(); - encoder.writeTkn(token); - const encoded = encoder.writer.flush(); - const decoded = decode(encoded); - expect(decoded).toBe(expected); - }); - }; - - testNativeToken(20, false); - testNativeToken(21, true); - testNativeToken(22, null); - testNativeToken(23, undefined); - - const testJsTokens = (token: unknown) => { - test(`can encode a token = ${token}`, () => { - const encoded = encoder.encode(token); - const decoded = decode(encoded); - expect(decoded).toBe(token); - }); - }; - - testJsTokens(false); - testJsTokens(true); - testJsTokens(null); - testJsTokens(undefined); -}); - -describe('JsonPackValue', () => { - test('can encode pre-packed value', () => { - const internal = encoder.encode({foo: 'bar'}); - const val = new JsonPackValue(internal); - const data = {boo: [1, val, 2]}; - const encoded = encoder.encode(data); - expect(decode(encoded)).toEqual({ - boo: [1, {foo: 'bar'}, 2], - }); - }); -}); diff --git a/src/json-pack/cbor/__tests__/CborEncoderDag.spec.ts b/src/json-pack/cbor/__tests__/CborEncoderDag.spec.ts deleted file mode 100644 index bde7883e02..0000000000 --- a/src/json-pack/cbor/__tests__/CborEncoderDag.spec.ts +++ /dev/null @@ -1,115 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {CborEncoderDag} from '../CborEncoderDag'; -import {CborDecoder} from '../CborDecoder'; -import {JsonPackExtension} from '../../JsonPackExtension'; -import {CborDecoderDag} from '../CborDecoderDag'; - -const writer = new Writer(1); -const encoder = new CborEncoderDag(writer); -const decoder = new CborDecoder(); - -describe('special tokens are not permitted', () => { - test('undefined', () => { - const encoded = encoder.encode(undefined); - const val = decoder.read(encoded); - expect(val).toBe(null); - expect(encoded.length).toBe(1); - }); - - test('NaN', () => { - const encoded = encoder.encode(NaN); - const val = decoder.read(encoded); - expect(val).toBe(null); - expect(encoded.length).toBe(1); - }); - - test('+Infinity', () => { - const encoded = encoder.encode(+Infinity); - const val = decoder.read(encoded); - expect(val).toBe(null); - expect(encoded.length).toBe(1); - }); - - test('-Infinity', () => { - const encoded = encoder.encode(-Infinity); - const val = decoder.read(encoded); - expect(val).toBe(null); - expect(encoded.length).toBe(1); - }); -}); - -describe('only extension = 42 is permitted', () => { - test('can encode a value with extension 42', () => { - const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(42, 'b')}); - const val = decoder.read(encoded); - expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - }); - - test('non-42 extensions are not encoded', () => { - const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(43, 'b')}); - const val = decoder.read(encoded); - expect(val).toStrictEqual({a: 'a', b: 'b'}); - }); - - class CID { - constructor(public readonly value: string) {} - } - class NotCID { - constructor(public readonly value: string) {} - } - - class IpfsCborEncoder extends CborEncoderDag { - public writeUnknown(val: unknown): void { - if (val instanceof CID) this.writeTag(42, val.value); - else throw new Error('Unknown value type'); - } - } - - class IpfsCborDecoder extends CborDecoderDag { - public readTagRaw(tag: number): CID | unknown { - if (tag === 42) return new CID(this.val() as any); - throw new Error('UNKNOWN_TAG'); - } - } - - test('can encode CID using inlined custom class', () => { - const encoder = new IpfsCborEncoder(); - const encoded = encoder.encode({a: 'a', b: new JsonPackExtension(42, 'b')}); - const val = decoder.read(encoded); - expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - const encoded2 = encoder.encode({a: 'a', b: new CID('b')}); - const val2 = decoder.decode(encoded2); - expect(val).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - expect(val2).toStrictEqual({a: 'a', b: new JsonPackExtension(42, 'b')}); - }); - - test('can encode CID inside a nested array', () => { - const encoder = new IpfsCborEncoder(); - const decoder = new IpfsCborDecoder(); - const cid = new CID('my-cid'); - const data = [1, [2, [3, cid, 4], 5], 6]; - const encoded = encoder.encode(data); - const decoded = decoder.decode(encoded); - expect(decoded).toStrictEqual(data); - }); - - test('can throw on unknown custom class', () => { - const encoder = new IpfsCborEncoder(); - const encoded1 = encoder.encode({a: 'a', b: new CID('b')}); - expect(() => encoder.encode({a: 'a', b: new NotCID('b')})).toThrowError(new Error('Unknown value type')); - }); -}); - -describe('floats', () => { - test('always encodes floats as double precision 64 bits', () => { - const floats = [ - 0.1, 0.2, 0.3, 0.4, 0.5, -0.1, -0.2, -0.3, -0.4, -0.5, 1.1, 1.12, 1.123, 1.1234, 0.12, 0.123, 0.1234, - ]; - const sizes = new Set(); - for (const float of floats) { - const encoded = encoder.encode(float); - sizes.add(encoded.length); - } - expect(sizes.size).toBe(1); - }); -}); diff --git a/src/json-pack/cbor/__tests__/CborEncoderStable.spec.ts b/src/json-pack/cbor/__tests__/CborEncoderStable.spec.ts deleted file mode 100644 index 6eff27187b..0000000000 --- a/src/json-pack/cbor/__tests__/CborEncoderStable.spec.ts +++ /dev/null @@ -1,227 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {CborEncoderStable} from '../CborEncoderStable'; -import {encode} from 'cborg'; - -const writer = new Writer(1); -const encoder = new CborEncoderStable(writer); - -describe('objects', () => { - test('sorts keys lexicographically', () => { - const obj1 = { - a: 1, - b: 2, - }; - const encoded1 = encoder.encode(obj1); - const encoded2 = encode(obj1); - expect(encoded1).toStrictEqual(encoded2); - const obj2 = { - b: 2, - a: 1, - }; - const encoded3 = encoder.encode(obj2); - const encoded4 = encode(obj2); - expect(encoded3).toStrictEqual(encoded4); - expect(encoded1).toStrictEqual(encoded3); - }); - - test('sorts keys by length', () => { - const obj1 = { - aa: 1, - b: 2, - }; - const encoded1 = encoder.encode(obj1); - const encoded2 = encode(obj1); - expect(encoded1).toStrictEqual(encoded2); - const obj2 = { - b: 2, - aa: 1, - }; - const encoded3 = encoder.encode(obj2); - const encoded4 = encode(obj2); - expect(encoded3).toStrictEqual(encoded4); - expect(encoded1).toStrictEqual(encoded3); - }); -}); - -describe('floats', () => { - test('always encoded as 8 bytes', () => { - for (let i = 0; i < 100; i++) { - const val = Math.random() * 100000; - const encoded1 = encoder.encode(val); - const encoded2 = encode(val); - expect(encoded1).toStrictEqual(encoded2); - expect(encoded1.length).toBe(9); - } - }); -}); - -describe('numbers and bigints', () => { - const assertNumber = (val: number, length: number) => { - const encoded1 = encoder.encode(val); - const encoded2 = encode(val); - expect(encoded1).toStrictEqual(encoded2); - expect(encoded1.length).toBe(length); - const encoded3 = encoder.encode(BigInt(val)); - expect(encoded1).toStrictEqual(encoded3); - }; - - describe('positive', () => { - test('numbers up to 23 are encoded as one byte', () => { - for (let i = 0; i < 24; i++) { - assertNumber(i, 1); - } - }); - - test('numbers between 24 and 0xff are encoded as two bytes', () => { - assertNumber(24, 2); - assertNumber(0xff, 2); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (0xff - 24) + 24); - assertNumber(val, 2); - } - }); - - test('numbers between 0xff + 1 and 0xffff are encoded as three bytes', () => { - assertNumber(0xff + 1, 3); - assertNumber(0xffff, 3); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (0xffff - (0xff + 1)) + 0xff + 1); - assertNumber(val, 3); - } - }); - - test('numbers between 0xffff + 1 and 0xffffffff are encoded as five bytes', () => { - assertNumber(0xffff + 1, 5); - assertNumber(0xffffffff, 5); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (0xffffffff - (0xffff + 1)) + 0xffff + 1); - assertNumber(val, 5); - } - }); - - test('numbers between 0xffffffff + 1 and Number.MAX_SAFE_INTEGER are encoded as nine bytes', () => { - assertNumber(0xffffffff + 1, 9); - assertNumber(Number.MAX_SAFE_INTEGER, 9); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (Number.MAX_SAFE_INTEGER - (0xffffffff + 1)) + 0xffffffff + 1); - assertNumber(val, 9); - } - }); - }); - - describe('negative', () => { - test('numbers between -24 and -1 are encoded as one byte', () => { - assertNumber(-24, 1); - assertNumber(-1, 1); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (-1 - -24) + -24); - assertNumber(val, 1); - } - }); - - test('numbers between -0xff - 1 and -25 are encoded as two bytes', () => { - assertNumber(-0xff, 2); - assertNumber(-0xff - 1, 2); - assertNumber(-25, 2); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (-25 - -0xff) + -0xff); - assertNumber(val, 2); - } - }); - - test('numbers between -0xffff - 1 and -0xff - 2 are encoded as three bytes', () => { - assertNumber(-0xffff, 3); - assertNumber(-0xff - 2, 3); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (-0xff - 2 - -0xffff) + -0xffff); - assertNumber(val, 3); - } - }); - - test('numbers between -0xffffffff - 1 and -0xffff - 2 are encoded as five bytes', () => { - assertNumber(-0xffffffff, 5); - assertNumber(-0xffff - 2, 5); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (-0xffff - 2 - -0xffffffff) + -0xffffffff); - assertNumber(val, 5); - } - }); - - test('numbers between Number.MIN_SAFE_INTEGER and -0xffffffff - 2 are encoded as nine bytes', () => { - assertNumber(Number.MIN_SAFE_INTEGER, 9); - assertNumber(-0xffffffff - 2, 9); - for (let i = 0; i < 100; i++) { - const val = Math.round(Math.random() * (-0xffffffff - 2 - Number.MIN_SAFE_INTEGER) + Number.MIN_SAFE_INTEGER); - assertNumber(val, 9); - } - }); - }); -}); - -describe('strings', () => { - const assertString = (val: string, length: number) => { - const encoded1 = encoder.encode(val); - expect(encoded1.length).toBe(length); - }; - - test('strings shorter than 24 byte consume 1 byte header', () => { - assertString('', 1); - assertString('a', 2); - assertString('a'.repeat(4), 5); - assertString('a'.repeat(8), 9); - assertString('a'.repeat(16), 17); - assertString('a'.repeat(23), 24); - }); - - test('strings between 24 and 0xff bytes consume 2 byte header', () => { - assertString('b'.repeat(24), 26); - assertString('b'.repeat(0xff), 0xff + 2); - for (let i = 0; i < 5; i++) { - const len = Math.round(Math.random() * (0xff - 24) + 24); - assertString('b'.repeat(len), len + 2); - } - }); - - test('strings between 0xff + 1 and 0xffff bytes consume 3 byte header', () => { - assertString('c'.repeat(0xff + 1), 0xff + 1 + 3); - assertString('c'.repeat(0xffff), 0xffff + 3); - for (let i = 0; i < 10; i++) { - const len = Math.round(Math.random() * (0xffff - (0xff + 1)) + 0xff + 1); - assertString('c'.repeat(len), len + 3); - } - }); - - test('strings between over 0xffff + 1 bytes consume 5 byte header', () => { - assertString('d'.repeat(0xffff + 1), 0xffff + 1 + 5); - for (let i = 0; i < 10; i++) { - const len = Math.round(Math.random() * (0xfffff - (0xffff + 1)) + 0xffff + 1); - assertString('c'.repeat(len), len + 5); - } - }); -}); - -describe('recursion', () => { - test('can prevent recursive objects', () => { - const encoder = new (class extends CborEncoderStable { - private readonly objectSet = new Set(); - - public encode(value: unknown): Uint8Array { - this.objectSet.clear(); - return super.encode(value); - } - - public writeAny(value: unknown): void { - if (this.objectSet.has(value)) { - throw new Error('Recursive object'); - } - this.objectSet.add(value); - super.writeAny(value); - } - })(); - const obj1 = {a: 1}; - const obj2 = {b: 2}; - (obj1).b = obj2; - (obj2).a = obj1; - expect(() => encoder.encode(obj1)).toThrowError('Recursive object'); - }); -}); diff --git a/src/json-pack/cbor/__tests__/cbor-js-testcases.ts b/src/json-pack/cbor/__tests__/cbor-js-testcases.ts deleted file mode 100644 index 4d8b4e03d6..0000000000 --- a/src/json-pack/cbor/__tests__/cbor-js-testcases.ts +++ /dev/null @@ -1,101 +0,0 @@ -import {ERROR} from '../constants'; - -export type TestCase = [name: string, expected: string, value: unknown, binaryDifference?: boolean, error?: ERROR]; - -export const testcases: TestCase[] = [ - ['PositiveIntegerFix 0', '00', 0], - ['PositiveIntegerFix 1', '01', 1], - ['PositiveIntegerFix 10', '0a', 10], - ['PositiveIntegerFix 23', '17', 23], - ['PositiveIntegerFix 24', '1818', 24], - ['PositiveInteger8 25', '1819', 25], - ['PositiveInteger8 100', '1864', 100], - ['PositiveInteger16 1000', '1903e8', 1000], - ['PositiveInteger32 1000000', '1a000f4240', 1000000], - ['PositiveInteger64 1000000000000', '1b000000e8d4a51000', 1000000000000], - ['PositiveInteger64 9007199254740991', '1b001fffffffffffff', 9007199254740991], - ['PositiveInteger64 9007199254740992', '1b0020000000000000', BigInt(9007199254740992)], - ['PositiveInteger64 18446744073709551615', '1bffffffffffffffff', BigInt('18446744073709551615'), true], - ['NegativeIntegerFix -1', '20', -1], - ['NegativeIntegerFix -10', '29', -10], - ['NegativeIntegerFix -24', '37', -24], - ['NegativeInteger8 -25', '3818', -25], - ['NegativeInteger8 -26', '3819', -26], - ['NegativeInteger8 -100', '3863', -100], - ['NegativeInteger16 -1000', '3903e7', -1000], - ['NegativeInteger32 -1000000', '3a000f423f', -1000000], - ['NegativeInteger64 -1000000000000', '3b000000e8d4a50fff', -1000000000000], - ['NegativeInteger64 -9007199254740992', '3b001fffffffffffff', BigInt(-9007199254740992)], - ['NegativeInteger64 -18446744073709551616', '3bffffffffffffffff', BigInt('-18446744073709551616'), true], - ["String ''", '60', ''], - ["String 'a'", '6161', 'a'], - ["String 'IETF'", '6449455446', 'IETF'], - ["String '\"\\'", '62225c', '"\\'], - ["String '\u00fc' (U+00FC)", '62c3bc', '\u00fc'], - ["String '\u6c34' (U+6C34)", '63e6b0b4', '\u6c34'], - ["String '\ud800\udd51' (U+10151)", '64f0908591', '\ud800\udd51'], - ["String 'streaming'", '7f657374726561646d696e67ff', 'streaming', true], - ['Array []', '80', []], - ["Array ['a', {'b': 'c'}]", '826161a161626163', ['a', {b: 'c'}]], - ["Array ['a, {_ 'b': 'c'}]", '826161bf61626163ff', ['a', {b: 'c'}], true], - ['Array [1,2,3]', '83010203', [1, 2, 3]], - ['Array [1, [2, 3], [4, 5]]', '8301820203820405', [1, [2, 3], [4, 5]]], - ['Array [1, [2, 3], [_ 4, 5]]', '83018202039f0405ff', [1, [2, 3], [4, 5]], true], - ['Array [1, [_ 2, 3], [4, 5]]', '83019f0203ff820405', [1, [2, 3], [4, 5]], true], - [ - 'Array [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]', - '98190102030405060708090a0b0c0d0e0f101112131415161718181819', - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], - ], - [ - 'Array [_ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]', - '9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff', - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], - true, - ], - ['Array [_ 1, [2, 3], [4, 5]]', '9f01820203820405ff', [1, [2, 3], [4, 5]], true], - ['Array [_ 1, [2, 3], [_ 4, 5]]', '9f018202039f0405ffff', [1, [2, 3], [4, 5]], true], - ['Array [_ ]', '9fff', [], true], - ['Object {}', 'a0', {}], - ['Object {1: 2, 3: 4}', 'a201020304', {1: 2, 3: 4}, true], - ["Object {'a': 1, 'b': [2, 3]}", 'a26161016162820203', {a: 1, b: [2, 3]}, true], - [ - "Object {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'E'}", - 'a56161614161626142616361436164614461656145', - {a: 'A', b: 'B', c: 'C', d: 'D', e: 'E'}, - true, - ], - ["Object {_ 'a': 1, 'b': [_ 2, 3]}", 'bf61610161629f0203ffff', {a: 1, b: [2, 3]}, true], - ["Object {_ 'Fun': true, 'Amt': -2}", 'bf6346756ef563416d7421ff', {Fun: true, Amt: -2}, true], - ['Tag Self-describe CBOR 0', 'd9d9f700', 0, true], - ['false', 'f4', false], - ['true', 'f5', true], - ['null', 'f6', null], - ['undefined', 'f7', undefined], - ['UnassignedSimpleValue 255', 'f8ff', 0xff, true], - ['Float16 0.0', 'f90000', 0.0, true], - // ['Float16 -0.0', 'f98000', -0.0, true], - ['Float16 1.0', 'f93c00', 1.0, true], - ['Float16 1.5', 'f93e00', 1.5, true], - ['Float16 65504.0', 'f97bff', 65504.0, true], - ['Float16 5.960464477539063e-8', 'f90001', 5.960464477539063e-8, true], - ['Float16 0.00006103515625', 'f90400', 0.00006103515625, true], - ['Float16 -5.960464477539063e-8', 'f98001', -5.960464477539063e-8, true], - ['Float16 -4.0', 'f9c400', -4.0, true], - ['Float16 +Infinity', 'f97c00', Infinity, true], - ['Float16 NaN', 'f97e00', NaN, true], - ['Float16 -Infinity', 'f9fc00', -Infinity, true], - ['Float32 100000.0', 'fa47c35000', 100000.0, true], - ['Float32 3.4028234663852886e+38', 'fa7f7fffff', 3.4028234663852886e38, true], - ['Float32 +Infinity', 'fa7f800000', Infinity, true], - ['Float32 NaN', 'fa7fc00000', NaN, true], - ['Float32 -Infinity', 'faff800000', -Infinity, true], - ['Float64 1.1', 'fb3ff199999999999a', 1.1], - ['Float64 9007199254740994', 'fb4340000000000001', 9007199254740994], - ['Float64 1.0e+300', 'fb7e37e43c8800759c', 1.0e300], - ['Float64 -4.1', 'fbc010666666666666', -4.1], - ['Float64 -9007199254740994', 'fbc340000000000001', -9007199254740994], - ['Float64 +Infinity', 'fb7ff0000000000000', Infinity, true], - ['Float64 NaN', 'fb7ff8000000000000', NaN, true], - ['Float64 -Infinity', 'fbfff0000000000000', -Infinity, true], -]; diff --git a/src/json-pack/cbor/__tests__/cbor-js.spec.ts b/src/json-pack/cbor/__tests__/cbor-js.spec.ts deleted file mode 100644 index 2c797bb3a8..0000000000 --- a/src/json-pack/cbor/__tests__/cbor-js.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import {testcases} from './cbor-js-testcases'; -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; -import {JsonPackExtension} from '../../JsonPackExtension'; -import {JsonPackValue} from '../../JsonPackValue'; - -const hex2arrayBuffer = (data: string): Uint8Array => { - const length = data.length / 2; - const ret = new Uint8Array(length); - for (let i = 0; i < length; ++i) { - ret[i] = parseInt(data.substr(i * 2, 2), 16); - } - return ret; -}; - -const run = (encoder: CborEncoder, decoder: CborDecoder) => { - describe('JSON documents', () => { - for (const [name, expected, value, binaryDifferences, error] of testcases) { - test(name, () => { - if (error === undefined) { - const expectedBuf = hex2arrayBuffer(expected); - const encoded = encoder.encode(value); - const decoded = decoder.decode(encoded); - if (!binaryDifferences) expect(encoded).toStrictEqual(expectedBuf); - expect(decoded).toStrictEqual(value); - const decoded2 = decoder.decode(expectedBuf); - const resultValue = - decoded2 instanceof JsonPackExtension - ? decoded2.val - : decoded2 instanceof JsonPackValue - ? decoded2.val - : decoded2; - expect(resultValue).toStrictEqual(value); - } else { - expect(() => decoder.decode(hex2arrayBuffer(expected))).toThrow(); - } - }); - } - }); -}; - -const encoder = new CborEncoder(); -const decoder = new CborDecoder(); - -run(encoder, decoder); diff --git a/src/json-pack/cbor/__tests__/codec.spec.ts b/src/json-pack/cbor/__tests__/codec.spec.ts deleted file mode 100644 index 63267aee27..0000000000 --- a/src/json-pack/cbor/__tests__/codec.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import {CborEncoder} from '../CborEncoder'; -import {CborEncoderFast} from '../CborEncoderFast'; -import {CborEncoderStable} from '../CborEncoderStable'; -import {CborEncoderDag} from '../CborEncoderDag'; -import {CborDecoder} from '../CborDecoder'; -import {decode as deocode__} from 'cbor'; -import {documents} from '../../../__tests__/json-documents'; -import {binaryDocuments} from '../../../__tests__/binary-documents'; - -const decode = (x: Uint8Array) => deocode__(x); -const decoder = new CborDecoder(); -const run = (encoder: CborEncoderFast) => { - describe('JSON documents', () => { - for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - const encoded = encoder.encode(t.json); - const decoded = decode(encoded); - expect(decoded).toEqual(t.json); - expect(decoder.decode(encoded)).toEqual(t.json); - - // Skipping - decoder.reader.reset(encoded); - const start = decoder.reader.x; - decoder.skipAny(); - const end = decoder.reader.x; - const diff = end - start; - expect(diff).toEqual(encoded.length); - }); - } - }); -}; - -const runBinary = (encoder: CborEncoderFast) => { - describe('binary documents', () => { - for (const t of binaryDocuments) { - (t.only ? test.only : test)(t.name, () => { - const encoded = encoder.encode(t.json); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(t.json); - - // Skipping - decoder.reader.reset(encoded); - const start = decoder.reader.x; - decoder.skipAny(); - const end = decoder.reader.x; - const diff = end - start; - expect(diff).toEqual(encoded.length); - }); - } - }); -}; - -describe('CbroEncoder', () => { - const encoder = new CborEncoder(); - run(encoder); - runBinary(encoder); -}); - -describe('CbroEncoderFast', () => { - const encoderFast = new CborEncoderFast(); - run(encoderFast); -}); - -describe('CbroEncoderStable', () => { - const encoderFast = new CborEncoderStable(); - run(encoderFast); -}); - -describe('CborEncoderDag', () => { - const encoderFast = new CborEncoderDag(); - run(encoderFast); -}); diff --git a/src/json-pack/cbor/__tests__/fuzzing.spec.ts b/src/json-pack/cbor/__tests__/fuzzing.spec.ts deleted file mode 100644 index f2709aa065..0000000000 --- a/src/json-pack/cbor/__tests__/fuzzing.spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -import {RandomJson} from '../../../json-random'; -import {CborEncoderFast} from '../CborEncoderFast'; -import {CborEncoder} from '../CborEncoder'; -import {CborEncoderStable} from '../CborEncoderStable'; -import {CborEncoderDag} from '../CborEncoderDag'; -import {CborDecoder} from '../CborDecoder'; - -const decoder = new CborDecoder(); - -describe('fuzzing', () => { - test('CborEncoderFast', () => { - const encoder = new CborEncoderFast(); - for (let i = 0; i < 200; i++) { - const value = RandomJson.generate(); - const encoded = encoder.encode(value); - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual(value); - } - }); - - test('CborEncoder', () => { - const encoder = new CborEncoder(); - for (let i = 0; i < 200; i++) { - const value = RandomJson.generate(); - const encoded = encoder.encode(value); - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual(value); - } - }); - - test('CborEncoderStable', () => { - const encoder = new CborEncoderStable(); - for (let i = 0; i < 200; i++) { - const value = RandomJson.generate(); - const encoded = encoder.encode(value); - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual(value); - } - }); - - test('CborEncoderDag', () => { - const encoder = new CborEncoderDag(); - for (let i = 0; i < 200; i++) { - const value = RandomJson.generate(); - const encoded = encoder.encode(value); - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual(value); - } - }); -}); diff --git a/src/json-pack/cbor/__tests__/shallow-read.genShallowRead.spec.ts b/src/json-pack/cbor/__tests__/shallow-read.genShallowRead.spec.ts deleted file mode 100644 index e68a278b19..0000000000 --- a/src/json-pack/cbor/__tests__/shallow-read.genShallowRead.spec.ts +++ /dev/null @@ -1,132 +0,0 @@ -import {genShallowReader} from '../../msgpack/shallow-read'; -import {CborEncoder} from '../CborEncoder'; -import {CborDecoder} from '../CborDecoder'; -import {Path} from '../../../json-pointer'; -import {Writer} from '../../../util/buffers/Writer'; - -const assetShallowRead = (doc: unknown, path: Path): void => { - const writer = new Writer(1); - const encoder = new CborEncoder(writer); - const encoded = encoder.encode(doc); - const decoder = new CborDecoder(); - decoder.reader.reset(encoded); - const res1 = decoder.find(path).reader.x; - // console.log(res1); - const fn = genShallowReader(path); - // console.log(fn.toString()); - decoder.reader.reset(encoded); - const res2 = fn(decoder as any); - // console.log(res2); - expect(res1).toBe(res2); -}; - -describe('genShallowRead', () => { - test('first-level object', () => { - const doc = { - bar: {}, - baz: 123, - gg: true, - }; - assetShallowRead(doc, ['bar']); - assetShallowRead(doc, ['baz']); - assetShallowRead(doc, ['gg']); - }); - - test('second-level object', () => { - const doc = { - a: { - bar: {}, - baz: 123, - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - assetShallowRead(doc, ['a']); - assetShallowRead(doc, ['a', 'bar']); - assetShallowRead(doc, ['a', 'baz']); - assetShallowRead(doc, ['a', 'gg']); - assetShallowRead(doc, ['b', 'mmmm']); - assetShallowRead(doc, ['b', 'mmmm', 's']); - assetShallowRead(doc, ['end']); - }); - - test('first-level array', () => { - const doc = [0]; - assetShallowRead(doc, [0]); - }); - - test('first-level array - 2', () => { - const doc = [1234, 'asdf', {}, null, false]; - assetShallowRead(doc, [0]); - assetShallowRead(doc, [1]); - assetShallowRead(doc, [2]); - assetShallowRead(doc, [3]); - assetShallowRead(doc, [4]); - }); - - test('throws when selector is out of bounds of array', () => { - const doc = [1234, 'asdf', {}, null, false]; - expect(() => assetShallowRead(doc, [5])).toThrowError(); - }); - - test('can read from complex nested document', () => { - const doc = { - a: { - bar: [ - { - a: 1, - 2: true, - asdf: false, - }, - 5, - ], - baz: ['a', 'b', 123], - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - assetShallowRead(doc, ['a']); - assetShallowRead(doc, ['a', 'bar', 0]); - assetShallowRead(doc, ['a', 'bar', 1]); - assetShallowRead(doc, ['a', 'bar', 0, 'a']); - assetShallowRead(doc, ['a', 'bar', 0, '2']); - assetShallowRead(doc, ['a', 'bar', 0, 'asdf']); - assetShallowRead(doc, ['b']); - assetShallowRead(doc, ['b', 'mmmm']); - assetShallowRead(doc, ['b', 'mmmm', 's']); - assetShallowRead(doc, ['end']); - }); - - test('should throw when key does not exist', () => { - const doc = { - a: { - bar: {}, - baz: 123, - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - const encoder = new CborEncoder(); - const encoded = encoder.encode(doc); - const decoder = new CborDecoder(); - decoder.reader.reset(encoded); - const fn = genShallowReader(['asdf']); - // console.log(fn.toString()); - expect(() => fn(decoder as any)).toThrowError(); - }); -}); diff --git a/src/json-pack/cbor/constants.ts b/src/json-pack/cbor/constants.ts deleted file mode 100644 index 86b3a5ae2b..0000000000 --- a/src/json-pack/cbor/constants.ts +++ /dev/null @@ -1,42 +0,0 @@ -export const enum MAJOR { - UIN = 0b000, - NIN = 0b001, - BIN = 0b010, - STR = 0b011, - ARR = 0b100, - MAP = 0b101, - TAG = 0b110, - TKN = 0b111, -} - -export const enum MAJOR_OVERLAY { - UIN = 0b000_00000, - NIN = 0b001_00000, - BIN = 0b010_00000, - STR = 0b011_00000, - ARR = 0b100_00000, - MAP = 0b101_00000, - TAG = 0b110_00000, - TKN = 0b111_00000, -} - -export const enum CONST { - MINOR_MASK = 0b11111, - MAX_UINT = 9007199254740991, - END = 0xff, -} - -export const enum ERROR { - UNEXPECTED_MAJOR, - UNEXPECTED_MINOR, - UNEXPECTED_BIN_CHUNK_MAJOR, - UNEXPECTED_BIN_CHUNK_MINOR, - UNEXPECTED_STR_CHUNK_MAJOR, - UNEXPECTED_STR_CHUNK_MINOR, - UNEXPECTED_OBJ_KEY, - UNEXPECTED_OBJ_BREAK, - INVALID_SIZE, - KEY_NOT_FOUND, - INDEX_OUT_OF_BOUNDS, - UNEXPECTED_STR_MAJOR, -} diff --git a/src/json-pack/cbor/shared.ts b/src/json-pack/cbor/shared.ts deleted file mode 100644 index 335f5f0783..0000000000 --- a/src/json-pack/cbor/shared.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {CborEncoder} from './CborEncoder'; -import {CborDecoder} from './CborDecoder'; -import {CborUint8Array} from './types'; - -export type {CborUint8Array}; - -export const encoder = new CborEncoder(); -export const decoder = new CborDecoder(); - -export const encode = (data: T): CborUint8Array => encoder.encode(data) as CborUint8Array; -export const decode = (blob: CborUint8Array): T => decoder.read(blob) as T; diff --git a/src/json-pack/cbor/types.ts b/src/json-pack/cbor/types.ts deleted file mode 100644 index d80243c3e2..0000000000 --- a/src/json-pack/cbor/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type CborUint8Array = Uint8Array & {__BRAND__: 'cbor'; __TYPE__: T}; diff --git a/src/json-pack/codecs/Codecs.ts b/src/json-pack/codecs/Codecs.ts deleted file mode 100644 index fa8c54f961..0000000000 --- a/src/json-pack/codecs/Codecs.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {Writer} from '../../util/buffers/Writer'; -import {CborJsonValueCodec} from './cbor'; -import {JsonJsonValueCodec} from './json'; -import {MsgPackJsonValueCodec} from './msgpack'; - -export class Codecs { - public readonly cbor: CborJsonValueCodec; - public readonly msgpack: MsgPackJsonValueCodec; - public readonly json: JsonJsonValueCodec; - - constructor(public readonly writer: Writer) { - this.cbor = new CborJsonValueCodec(this.writer); - this.msgpack = new MsgPackJsonValueCodec(this.writer); - this.json = new JsonJsonValueCodec(this.writer); - } -} diff --git a/src/json-pack/codecs/cbor.ts b/src/json-pack/codecs/cbor.ts deleted file mode 100644 index 88f35dcd9f..0000000000 --- a/src/json-pack/codecs/cbor.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {CborDecoder} from '../cbor/CborDecoder'; -import {CborEncoder} from '../cbor/CborEncoder'; -import {EncodingFormat} from '../constants'; -import type {Writer} from '../../util/buffers/Writer'; -import type {JsonValueCodec} from './types'; - -export class CborJsonValueCodec implements JsonValueCodec { - public readonly id = 'cbor'; - public readonly format = EncodingFormat.Cbor; - public readonly encoder: CborEncoder; - public readonly decoder: CborDecoder; - - constructor(writer: Writer) { - this.encoder = new CborEncoder(writer); - this.decoder = new CborDecoder(); - } -} diff --git a/src/json-pack/codecs/json.ts b/src/json-pack/codecs/json.ts deleted file mode 100644 index 14f3297819..0000000000 --- a/src/json-pack/codecs/json.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {EncodingFormat} from '../constants'; -import {JsonEncoder} from '../json/JsonEncoder'; -import {JsonDecoder} from '../json/JsonDecoder'; -import type {Writer} from '../../util/buffers/Writer'; -import type {JsonValueCodec} from './types'; - -export class JsonJsonValueCodec implements JsonValueCodec { - public readonly id = 'json'; - public readonly format = EncodingFormat.Json; - public readonly encoder: JsonEncoder; - public readonly decoder: JsonDecoder; - - constructor(writer: Writer) { - this.encoder = new JsonEncoder(writer); - this.decoder = new JsonDecoder(); - } -} diff --git a/src/json-pack/codecs/msgpack.ts b/src/json-pack/codecs/msgpack.ts deleted file mode 100644 index 00356d6583..0000000000 --- a/src/json-pack/codecs/msgpack.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {EncodingFormat} from '../constants'; -import {MsgPackEncoder} from '../msgpack'; -import {MsgPackDecoder} from '../msgpack/MsgPackDecoder'; -import type {Writer} from '../../util/buffers/Writer'; -import type {JsonValueCodec} from './types'; - -export class MsgPackJsonValueCodec implements JsonValueCodec { - public readonly id = 'msgpack'; - public readonly format = EncodingFormat.MsgPack; - public readonly encoder: MsgPackEncoder; - public readonly decoder: MsgPackDecoder; - - constructor(writer: Writer) { - this.encoder = new MsgPackEncoder(writer); - this.decoder = new MsgPackDecoder(); - } -} diff --git a/src/json-pack/codecs/types.ts b/src/json-pack/codecs/types.ts deleted file mode 100644 index 40c0a51d7e..0000000000 --- a/src/json-pack/codecs/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type {EncodingFormat} from '../constants'; -import type {BinaryJsonDecoder, BinaryJsonEncoder} from '../types'; - -export interface JsonValueCodec { - id: string; - format: EncodingFormat; - encoder: BinaryJsonEncoder; - decoder: BinaryJsonDecoder; -} diff --git a/src/json-pack/constants.ts b/src/json-pack/constants.ts deleted file mode 100644 index 5fd85b0f78..0000000000 --- a/src/json-pack/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const enum EncodingFormat { - Cbor, - MsgPack, - Json, -} diff --git a/src/json-pack/ion/Import.ts b/src/json-pack/ion/Import.ts deleted file mode 100644 index cf240d53e6..0000000000 --- a/src/json-pack/ion/Import.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {AstNode, ObjAstNode, toAst} from './ast'; -import {SymbolTable} from './types'; - -export class Import { - public readonly offset: number; - public length: number; - protected readonly byText = new Map(); - - constructor( - public readonly parent: Import | null, - public readonly symbols: SymbolTable, - ) { - this.offset = parent ? parent.offset + parent.length : 1; - this.length = symbols.length; - for (let i = 0; i < symbols.length; i++) { - const symbol = symbols[i]; - this.byText.set(symbol, this.offset + i); - } - } - - public getId(symbol: string): number | undefined { - const id = this.byText.get(symbol); - if (id !== undefined) return id; - if (this.parent) this.parent.getId(symbol); - return undefined; - } - - public getText(id: number): string | undefined { - if (id < this.offset) return this.parent ? this.parent.getText(id) : undefined; - return this.symbols[id - this.offset]; - } - - public add(symbol: string): number { - let id = this.byText.get(symbol); - if (id !== undefined) return id; - const length = this.symbols.length; - id = this.offset + length; - this.symbols.push(symbol); - this.length++; - this.byText.set(symbol, id); - return id; - } - - public toAst(): ObjAstNode { - const map = new Map>(); - map.set(7, toAst(this.symbols, this)); - return new ObjAstNode(map); - } -} diff --git a/src/json-pack/ion/IonEncoderFast.ts b/src/json-pack/ion/IonEncoderFast.ts deleted file mode 100644 index dd19be1c8d..0000000000 --- a/src/json-pack/ion/IonEncoderFast.ts +++ /dev/null @@ -1,234 +0,0 @@ -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import {Writer} from '../../util/buffers/Writer'; -import { - AnnotationAstNode, - ArrAstNode, - AstNode, - BinAstNode, - BoolAstNode, - FloatAstNode, - NintAstNode, - NullAstNode, - ObjAstNode, - StrAstNode, - toAst, - UintAstNode, -} from './ast'; -import {TYPE_OVERLAY} from './constants'; -import {Import} from './Import'; -import {systemSymbolImport} from './symbols'; - -export class IonEncoderFast { - protected symbols?: Import; - - constructor(public readonly writer: IWriter & IWriterGrowable = new Writer()) {} - - public encode(value: unknown): Uint8Array { - this.writer.reset(); - this.symbols = new Import(systemSymbolImport, []); - const ast = toAst(value, this.symbols); - this.writeIvm(); - this.writeSymbolTable(); - this.writeAny(ast); - return this.writer.flush(); - } - - public writeAny(value: AstNode): void { - if (value instanceof NullAstNode) this.writer.u8(TYPE_OVERLAY.NULL + 15); - else if (value instanceof StrAstNode) this.writeStr(value); - else if (value instanceof UintAstNode) this.encodeUint(value); - else if (value instanceof NintAstNode) this.encodeNint(value); - else if (value instanceof ObjAstNode) this.writeObj(value); - else if (value instanceof ArrAstNode) this.writeArr(value); - else if (value instanceof FloatAstNode) this.writeFloat(value); - else if (value instanceof BoolAstNode) this.writeBool(value); - else if (value instanceof BinAstNode) this.writeBin(value); - } - - public writeIvm(): void { - this.writer.u32(0xe00100ea); - } - - public writeSymbolTable(): void { - if (!this.symbols?.length) return; - const node = new AnnotationAstNode(this.symbols!.toAst(), [3]); - this.writeAnnotations(node); - } - - public writeAnnotations(node: AnnotationAstNode): void { - const writer = this.writer; - if (node.len < 14) writer.u8(TYPE_OVERLAY.ANNO + node.len); - else { - writer.u8(TYPE_OVERLAY.ANNO + 14); - this.writeVUint(node.len); - } - this.writeVUint(node.annotationLen); - for (let i = 0; i < node.annotations.length; i++) this.writeVUint(node.annotations[i]); - this.writeAny(node.val); - } - - public writeBool(node: BoolAstNode): void { - this.writer.u8(TYPE_OVERLAY.BOOL + (node.val ? 1 : 0)); - } - - public encodeUint(node: UintAstNode): void { - const uint = node.val; - if (!uint) this.writer.u8(TYPE_OVERLAY.UINT); - else if (uint <= 0xff) this.writer.u16(((TYPE_OVERLAY.UINT + 1) << 8) + uint); - else if (uint <= 0xffff) this.writer.u8u16(TYPE_OVERLAY.UINT + 2, uint); - else if (uint <= 0xffffff) this.writer.u32(((TYPE_OVERLAY.UINT + 3) << 24) + uint); - else if (uint <= 0xffffffff) this.writer.u8u32(TYPE_OVERLAY.UINT + 4, uint); - else { - let lo = uint | 0; - if (lo < 0) lo += 4294967296; - let hi = uint - lo; - hi /= 4294967296; - if (uint <= 0xffffffffff) { - this.writer.u16(((TYPE_OVERLAY.UINT + 5) << 8) + hi); - this.writer.u32(lo); - } else if (uint <= 0xffffffffffff) { - this.writer.u8u16(TYPE_OVERLAY.UINT + 6, hi); - this.writer.u32(lo); - } else { - this.writer.u16(((TYPE_OVERLAY.UINT + 7) << 8) + (hi >> 16)); - this.writer.u16(hi & 0xffff); - this.writer.u32(lo); - } - } - } - - public encodeNint(node: NintAstNode): void { - const uint = -node.val; - if (uint <= 0xff) this.writer.u16(((TYPE_OVERLAY.NINT + 1) << 8) + uint); - else if (uint <= 0xffff) this.writer.u8u16(TYPE_OVERLAY.NINT + 2, uint); - else if (uint <= 0xffffff) this.writer.u32(((TYPE_OVERLAY.NINT + 3) << 24) + uint); - else if (uint <= 0xffffffff) this.writer.u8u32(TYPE_OVERLAY.NINT + 4, uint); - else { - let lo = uint | 0; - if (lo < 0) lo += 4294967296; - let hi = uint - lo; - hi /= 4294967296; - if (uint <= 0xffffffffff) { - this.writer.u16(((TYPE_OVERLAY.NINT + 5) << 8) + hi); - this.writer.u32(lo); - } else if (uint <= 0xffffffffffff) { - this.writer.u8u16(TYPE_OVERLAY.NINT + 6, hi); - this.writer.u32(lo); - } else { - this.writer.u16(((TYPE_OVERLAY.NINT + 7) << 8) + (hi >> 16)); - this.writer.u16(hi & 0xffff); - this.writer.u32(lo); - } - } - } - - public writeFloat(node: FloatAstNode): void { - this.writer.u8f64(TYPE_OVERLAY.FLOT + 8, node.val); - } - - public writeVUint(num: number): void { - const writer = this.writer; - if (num <= 0b1111111) { - writer.u8(0b10000000 + num); - } else if (num <= 0b1111111_1111111) { - writer.ensureCapacity(2); - const uint8 = writer.uint8; - uint8[writer.x++] = num >>> 7; - uint8[writer.x++] = 0b10000000 + (num & 0b01111111); - } else if (num <= 0b1111111_1111111_1111111) { - writer.ensureCapacity(3); - const uint8 = writer.uint8; - uint8[writer.x++] = num >>> 14; - uint8[writer.x++] = (num >>> 7) & 0b01111111; - uint8[writer.x++] = 0b10000000 + (num & 0b01111111); - } else if (num <= 0b1111111_1111111_1111111_1111111) { - writer.ensureCapacity(4); - const uint8 = writer.uint8; - uint8[writer.x++] = num >>> 21; - uint8[writer.x++] = (num >>> 14) & 0b01111111; - uint8[writer.x++] = (num >>> 7) & 0b01111111; - uint8[writer.x++] = 0b10000000 + (num & 0b01111111); - } else { - let lo32 = num | 0; - if (lo32 < 0) lo32 += 4294967296; - const hi32 = (num - lo32) / 4294967296; - if (num <= 0b1111111_1111111_1111111_1111111_1111111) { - writer.ensureCapacity(5); - const uint8 = writer.uint8; - uint8[writer.x++] = (hi32 << 4) | (num >>> 28); - uint8[writer.x++] = (num >>> 21) & 0b01111111; - uint8[writer.x++] = (num >>> 14) & 0b01111111; - uint8[writer.x++] = (num >>> 7) & 0b01111111; - uint8[writer.x++] = 0b10000000 + (num & 0b01111111); - } else if (num <= 0b1111111_1111111_1111111_1111111_1111111_1111111) { - writer.ensureCapacity(6); - const uint8 = writer.uint8; - uint8[writer.x++] = (hi32 >>> 3) & 0b1111; - uint8[writer.x++] = ((hi32 & 0b111) << 4) | (num >>> 28); - uint8[writer.x++] = (num >>> 21) & 0b01111111; - uint8[writer.x++] = (num >>> 14) & 0b01111111; - uint8[writer.x++] = (num >>> 7) & 0b01111111; - uint8[writer.x++] = 0b10000000 + (num & 0b01111111); - } - } - } - - public writeStr(node: StrAstNode): void { - const str = node.val; - const length = node.len; - const writer = this.writer; - if (length < 14) writer.u8(TYPE_OVERLAY.STRI + length); - else { - writer.u8(TYPE_OVERLAY.STRI + 14); - this.writeVUint(length); - } - writer.utf8(str); - } - - public writeBin(node: BinAstNode): void { - const buf = node.val; - const length = node.len; - const writer = this.writer; - if (length < 14) writer.u8(TYPE_OVERLAY.BINA + length); - else { - writer.u8(TYPE_OVERLAY.BINA + 14); - this.writeVUint(length); - } - writer.buf(buf, length); - } - - public writeArr(node: ArrAstNode): void { - const writer = this.writer; - const arr = node.val; - if (arr === null) { - writer.u8(TYPE_OVERLAY.LIST + 15); - return; - } - const length = node.len; - if (length < 14) writer.u8(TYPE_OVERLAY.LIST + length); - else { - writer.u8(TYPE_OVERLAY.LIST + 14); - this.writeVUint(length); - } - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - } - - public writeObj(node: ObjAstNode): void { - const writer = this.writer; - const arr = node.val; - if (arr === null) { - writer.u8(TYPE_OVERLAY.LIST + 15); - return; - } - const length = node.len; - if (length < 14) writer.u8(TYPE_OVERLAY.STRU + length); - else { - writer.u8(TYPE_OVERLAY.STRU + 14); - this.writeVUint(length); - } - node.val!.forEach((n, symbolId) => { - this.writeVUint(symbolId); - this.writeAny(n); - }); - } -} diff --git a/src/json-pack/ion/README.md b/src/json-pack/ion/README.md deleted file mode 100644 index 88a4bce328..0000000000 --- a/src/json-pack/ion/README.md +++ /dev/null @@ -1,59 +0,0 @@ -## Benchmarks - -Encoding: - -``` -npx ts-node benchmarks/json-pack/bench.ion.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 Max ----------------------------------------------------------------------------- Small object, 44 bytes -👍 json-joy/json-pack IonEncoderFast x 1,021,876 ops/sec ±0.47% (99 runs sampled) -👍 ion-js x 27,391 ops/sec ±2.69% (68 runs sampled) -👍 Buffer.from(JSON.stringify()) x 2,269,009 ops/sec ±0.40% (99 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) -------------------------------------------------------------------------- Typical object, 993 bytes -👍 json-joy/json-pack IonEncoderFast x 69,443 ops/sec ±0.35% (99 runs sampled) -👎 ion-js x 3,723 ops/sec ±3.07% (53 runs sampled) -👎 Buffer.from(JSON.stringify()) x 214,308 ops/sec ±0.34% (98 runs sampled) -Fastest is 👎 Buffer.from(JSON.stringify()) --------------------------------------------------------------------------- Large object, 3741 bytes -👍 json-joy/json-pack IonEncoderFast x 11,696 ops/sec ±0.33% (101 runs sampled) -👎 ion-js x 1,213 ops/sec ±2.93% (62 runs sampled) -👎 Buffer.from(JSON.stringify()) x 67,074 ops/sec ±0.35% (96 runs sampled) -Fastest is 👎 Buffer.from(JSON.stringify()) --------------------------------------------------------------------- Very large object, 45750 bytes -👍 json-joy/json-pack IonEncoderFast x 1,892 ops/sec ±0.43% (100 runs sampled) -👍 ion-js x 65.56 ops/sec ±3.14% (58 runs sampled) -👍 Buffer.from(JSON.stringify()) x 5,957 ops/sec ±0.36% (97 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 json-joy/json-pack IonEncoderFast x 64,855 ops/sec ±0.32% (96 runs sampled) -👎 ion-js x 2,299 ops/sec ±4.32% (51 runs sampled) -👎 Buffer.from(JSON.stringify()) x 174,044 ops/sec ±0.32% (97 runs sampled) -Fastest is 👎 Buffer.from(JSON.stringify()) -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 json-joy/json-pack IonEncoderFast x 26,020 ops/sec ±0.33% (99 runs sampled) -👍 ion-js x 10,668 ops/sec ±5.02% (80 runs sampled) -👍 Buffer.from(JSON.stringify()) x 129,722 ops/sec ±0.35% (96 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) --------------------------------------------------------------------------- Long strings, 7011 bytes -👎 json-joy/json-pack IonEncoderFast x 11,837 ops/sec ±0.49% (96 runs sampled) -👍 ion-js x 8,749 ops/sec ±3.80% (85 runs sampled) -👍 Buffer.from(JSON.stringify()) x 29,769 ops/sec ±0.36% (101 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) --------------------------------------------------------------------------- Short strings, 170 bytes -👍 json-joy/json-pack IonEncoderFast x 435,230 ops/sec ±0.39% (96 runs sampled) -👍 ion-js x 42,636 ops/sec ±8.11% (66 runs sampled) -👍 Buffer.from(JSON.stringify()) x 1,013,889 ops/sec ±0.46% (96 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 json-joy/json-pack IonEncoderFast x 484,353 ops/sec ±0.41% (97 runs sampled) -👍 ion-js x 17,032 ops/sec ±14.67% (70 runs sampled) -👍 Buffer.from(JSON.stringify()) x 1,196,228 ops/sec ±0.40% (99 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 json-joy/json-pack IonEncoderFast x 328,346 ops/sec ±0.45% (96 runs sampled) -👍 ion-js x 55,922 ops/sec ±4.56% (79 runs sampled) -👍 Buffer.from(JSON.stringify()) x 991,593 ops/sec ±0.45% (97 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()) -``` diff --git a/src/json-pack/ion/__tests__/Import.spec.ts b/src/json-pack/ion/__tests__/Import.spec.ts deleted file mode 100644 index 5288aab6ea..0000000000 --- a/src/json-pack/ion/__tests__/Import.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {Import} from '../Import'; -import {systemSymbolImport, systemSymbolTable} from '../symbols'; - -test('can instantiate symbols to local symbol table import', () => { - const imp = new Import(systemSymbolImport, ['foo', 'bar']); - const fooId = imp.getId('foo'); - const barId = imp.getId('bar'); - expect(fooId).toBe(systemSymbolTable.length + 1); - expect(barId).toBe(systemSymbolTable.length + 2); - const barText = imp.getText(systemSymbolTable.length + 1); - const fooText = imp.getText(systemSymbolTable.length + 2); - expect(barText).toBe('foo'); - expect(fooText).toBe('bar'); -}); - -test('can add symbols to the local symbol table import', () => { - const imp = new Import(systemSymbolImport, ['foo', 'bar']); - imp.add('baz'); - imp.add('__proto__'); - const id1 = imp.getId('baz'); - const id2 = imp.getId('__proto__'); - expect(id1).toBe(systemSymbolTable.length + 3); - expect(id2).toBe(systemSymbolTable.length + 4); - const text1 = imp.getText(systemSymbolTable.length + 3); - const text2 = imp.getText(systemSymbolTable.length + 4); - expect(text1).toBe('baz'); - expect(text2).toBe('__proto__'); -}); - -test('returns ID of new local symbol', () => { - const imp = new Import(systemSymbolImport, []); - const id = imp.add('baz'); - expect(id).toBe(systemSymbolTable.length + 1); - const id2 = imp.getId('baz'); - expect(id2).toBe(systemSymbolTable.length + 1); -}); - -test('returns same ID when adding symbol with the same text', () => { - const imp = new Import(systemSymbolImport, []); - const id1 = imp.add('baz'); - const id2 = imp.add('bar'); - const id3 = imp.add('baz'); - expect(id1).toBe(id3); - expect(id1).not.toBe(id2); - expect(imp.add('bar')).toBe(id2); - expect(imp.add('bar')).toBe(id2); -}); diff --git a/src/json-pack/ion/__tests__/IonEncoder.spec.ts b/src/json-pack/ion/__tests__/IonEncoder.spec.ts deleted file mode 100644 index c7f55ee716..0000000000 --- a/src/json-pack/ion/__tests__/IonEncoder.spec.ts +++ /dev/null @@ -1,212 +0,0 @@ -import {IonEncoderFast} from '../IonEncoderFast'; -import {makeBinaryWriter, dom} from 'ion-js'; - -const encode = (value: unknown): Uint8Array => { - const writer = makeBinaryWriter(); - dom.Value.from(value)?.writeTo(writer); - writer.close(); - return writer.getBytes(); -}; - -const encoder = new IonEncoderFast(); - -describe('tokens', () => { - const tokens: unknown[] = [true, false, null]; - - for (const bool of tokens) { - test(`${bool}`, () => { - const encoded = encoder.encode(bool); - expect(encoded).toEqual(encode(bool)); - }); - } -}); - -describe('integers', () => { - const ints: number[] = [ - 0, - 1, - 2, - 3, - 128, - 254, - 255, - 256, - 257, - 65535, - 2 ** 16 - 2, - 2 ** 16 - 1, - 2 ** 16 - 0, - 2 ** 16 + 1, - 2 ** 16 + 2, - 2 ** 24 - 2, - 2 ** 24 - 1, - 2 ** 24 - 0, - 2 ** 24 + 1, - 2 ** 24 + 2, - 2 ** 32 - 2, - 2 ** 32 - 1, - 2 ** 32 - 0, - 2 ** 32 + 1, - 2 ** 32 + 2, - 2 ** 40 - 2, - 2 ** 40 - 0, - 2 ** 40 + 1, - 2 ** 40 + 2, - 2 ** 48 - 2, - 2 ** 48 - 1, - 2 ** 48 - 0, - 2 ** 48 + 1, - 2 ** 48 + 2, - 2 ** 53 - 1, - ]; - - for (const value of ints) { - test(`${value}`, () => { - const encoded = encoder.encode(value); - expect(encoded).toEqual(encode(value)); - }); - } - for (const value of ints) { - test(`${-value}`, () => { - const encoded = encoder.encode(-value); - expect(encoded).toEqual(encode(-value)); - }); - } -}); - -describe('floats', () => { - const values: number[] = [ - 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.123, 0.1234, 0.12345, 1.1, 123.123, 3.14, 3.14159, 4.23, 7.22, - ]; - - for (const value of values) { - test(`${value}`, () => { - const encoded = encoder.encode(value); - expect(encoded).toEqual(encode(value)); - }); - } - for (const value of values) { - test(`${-value}`, () => { - const encoded = encoder.encode(-value); - expect(encoded).toEqual(encode(-value)); - }); - } -}); - -describe('strings', () => { - const values: string[] = [ - '', - 'a', - 'ab', - 'abc', - 'abcd', - 'abcde', - 'abcdef', - 'abcdefg', - 'abcdefgh', - 'abcdefghi', - 'abcdefghij', - 'abcdefghijk', - 'abcdefghijkl', - 'abcdefghijklm', - 'abcdefghijklmn', - 'abcdefghijklmno', - 'abcdefghijklmnop', - 'abcdefghijklmnopq', - 'abcdefghijklmnopqr', - 'abcdefghijklmnopqrs', - 'abcdefghijklmnopqrst', - 'abcdefghijklmnopqrstu', - 'abcdefghijklmnopqrstuv', - 'abcdefghijklmnopqrstuvw', - 'abcdefghijklmnopqrstuvwx', - 'abcdefghijklmnopqrstuvwxy', - 'abcdefghijklmnopqrstuvwxyz', - '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567', - 'a'.repeat(20000), - ]; - - for (const value of values) { - test(`${value.substring(0, 80)}`, () => { - const encoded = encoder.encode(value); - const expected = encode(value); - // console.log(encoded); - // console.log(expected); - expect(encoded).toEqual(expected); - }); - } -}); - -describe('binary', () => { - const values: Uint8Array[] = [ - new Uint8Array(), - new Uint8Array([0]), - new Uint8Array([1, 2, 3]), - new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]), - new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]), - ]; - - for (const value of values) { - test(`${value}`, () => { - const encoded = encoder.encode(value); - const expected = encode(value); - // console.log(encoded); - // console.log(expected); - expect(encoded).toEqual(expected); - }); - } -}); - -describe('arrays', () => { - const values: unknown[][] = [ - [], - [''], - ['asdf'], - [0], - [0, 0, 0], - [0, 1], - [1, 2, 3, 4, 5, 6], - [1, 2, 3, 4, 5, 6, 7], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], - [[]], - [[1, 2, 3]], - [[1, 2, 3, 'x'], 'asdf', null, false, true], - ]; - - for (const value of values) { - test(`${JSON.stringify(value)}`, () => { - const encoded = encoder.encode(value); - expect(encoded).toEqual(encode(value)); - }); - } -}); - -describe('objects', () => { - const values: object[] = [ - {}, - {a: 1}, - {a: 'b', foo: 'bar'}, - {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, o: 15, p: 16}, - { - foo: [ - 'bar', - 1, - null, - { - a: 'gg', - d: 123, - }, - ], - }, - ]; - - for (const value of values) { - test(`${JSON.stringify(value)}`, () => { - const encoded = encoder.encode(value); - const expected = encode(value); - // console.log(encoded); - // console.log(expected); - expect(encoded).toEqual(expected); - }); - } -}); diff --git a/src/json-pack/ion/__tests__/automated.spec.ts b/src/json-pack/ion/__tests__/automated.spec.ts deleted file mode 100644 index d317e93abf..0000000000 --- a/src/json-pack/ion/__tests__/automated.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {IonEncoderFast} from '../IonEncoderFast'; -import {load} from 'ion-js'; -import {documents} from '../../../__tests__/json-documents'; - -const encoder = new IonEncoderFast(); - -for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - const encoded = encoder.encode(t.json); - // console.log(encoded); - const decoded = load(encoded); - const pojo = JSON.parse(JSON.stringify(decoded)); - expect(pojo).toEqual(t.json); - }); -} diff --git a/src/json-pack/ion/ast.ts b/src/json-pack/ion/ast.ts deleted file mode 100644 index 9c56309f9e..0000000000 --- a/src/json-pack/ion/ast.ts +++ /dev/null @@ -1,185 +0,0 @@ -import {utf8Size} from '../../util/strings/utf8'; -import {Import} from './Import'; - -export interface AstNode { - /** Node value as JS value. */ - readonly val: T; - /** Node representation length. */ - readonly len: number; - /** Total length of the node. */ - byteLength(): number; -} - -export class NullAstNode implements AstNode { - public readonly val = null; - public readonly len = 1; - public byteLength(): number { - return 1; - } -} - -export class BoolAstNode implements AstNode { - public readonly len = 1; - constructor(public readonly val: boolean) {} - public byteLength(): number { - return 1; - } -} - -export class UintAstNode implements AstNode { - public readonly len: number; - constructor(public readonly val: number) { - if (!val) this.len = 0; - else if (val <= 0xff) this.len = 1; - else if (val <= 0xffff) this.len = 2; - else if (val <= 0xffffff) this.len = 3; - else if (val <= 0xffffffff) this.len = 4; - else if (val <= 0xffffffffff) this.len = 5; - else if (val <= 0xffffffffffff) this.len = 6; - else this.len = 7; - } - public byteLength(): number { - return 1 + this.len; - } -} - -export class NintAstNode implements AstNode { - public readonly len: number; - constructor(public readonly val: number) { - const uint = -val; - if (!uint) this.len = 0; - else if (uint <= 0xff) this.len = 1; - else if (uint <= 0xffff) this.len = 2; - else if (uint <= 0xffffff) this.len = 3; - else if (uint <= 0xffffffff) this.len = 4; - else if (uint <= 0xffffffffff) this.len = 5; - else if (uint <= 0xffffffffffff) this.len = 6; - else this.len = 7; - } - public byteLength(): number { - return 1 + this.len; - } -} - -export class FloatAstNode implements AstNode { - public readonly len: number = 8; - constructor(public readonly val: number) {} - public byteLength(): number { - return 1 + this.len; - } -} - -const vUintLen = (num: number): number => { - if (num <= 0b1111111) return 1; - else if (num <= 0b1111111_1111111) return 2; - else if (num <= 0b1111111_1111111_1111111) return 3; - else if (num <= 0b1111111_1111111_1111111_1111111) return 4; - else if (num <= 0b1111111_1111111_1111111_1111111_1111111) return 5; - else return 6; -}; - -export class StrAstNode implements AstNode { - public readonly len: number; - constructor(public readonly val: string) { - this.len = utf8Size(val); - } - public byteLength(): number { - return this.len < 14 ? 1 + this.len : 1 + vUintLen(this.len) + this.len; - } -} - -export class BinAstNode implements AstNode { - public readonly len: number; - constructor(public readonly val: Uint8Array) { - this.len = val.length; - } - public byteLength(): number { - return this.len < 14 ? 1 + this.len : 1 + vUintLen(this.len) + this.len; - } -} - -export class ArrAstNode implements AstNode[] | null> { - public readonly len: number; - constructor(public readonly val: AstNode[] | null) { - if (val === null) { - this.len = 1; - } else { - if (!val.length) this.len = 0; - else { - let elementLength = 0; - for (let i = 0; i < val.length; i++) elementLength += val[i].byteLength(); - this.len = elementLength; - } - } - } - public byteLength(): number { - return this.len < 14 ? 1 + this.len : 1 + vUintLen(this.len) + this.len; - } -} - -export class ObjAstNode implements AstNode> | null> { - public readonly len: number; - constructor(public readonly val: Map> | null) { - if (val === null) { - this.len = 1; - } else { - if (!val.size) this.len = 0; - else { - let len = 0; - val.forEach((node, symbolId) => { - len += vUintLen(symbolId) + node.byteLength(); - }); - this.len = len; - } - } - } - public byteLength(): number { - return this.len < 14 ? 1 + this.len : 1 + vUintLen(this.len) + this.len; - } -} - -export class AnnotationAstNode implements AstNode> { - public readonly len: number; - public readonly annotationLen: number; - constructor( - public readonly val: AstNode, - public readonly annotations: number[], - ) { - let len = 0; - for (let i = 0; i < annotations.length; i++) len += vUintLen(annotations[i]); - this.annotationLen = len; - len += vUintLen(len); - len += val.byteLength(); - this.len = len; - } - public byteLength(): number { - return this.len < 14 ? 1 + this.len : 1 + vUintLen(this.len) + this.len; - } -} - -const isSafeInteger = Number.isSafeInteger; - -export const toAst = (val: unknown, symbols: Import): AstNode => { - if (val === null) return new NullAstNode(); - if (val instanceof Array) return new ArrAstNode(val.map((el) => toAst(el, symbols))); - if (val instanceof Uint8Array) return new BinAstNode(val); - switch (typeof val) { - case 'boolean': - return new BoolAstNode(val); - case 'number': { - if (isSafeInteger(val)) return val >= 0 ? new UintAstNode(val) : new NintAstNode(val); - else return new FloatAstNode(val); - } - case 'string': - return new StrAstNode(val); - case 'object': { - const struct = new Map>(); - for (const key in val) { - const symbolId = symbols.add(key); - struct.set(symbolId, toAst((val as any)[key], symbols)); - } - return new ObjAstNode(struct); - } - } - throw new Error('UNKNOWN_TYPE'); -}; diff --git a/src/json-pack/ion/constants.ts b/src/json-pack/ion/constants.ts deleted file mode 100644 index 2729622b7e..0000000000 --- a/src/json-pack/ion/constants.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const enum TYPE { - NULL = 0b0000, - BOOL = 0b0001, - UINT = 0b0010, - NINT = 0b0011, - FLOT = 0b0100, - STRI = 0b1000, - LIST = 0b1011, - BINA = 0b1010, - STRU = 0b1101, - ANNO = 0b1110, -} - -export const enum TYPE_OVERLAY { - NULL = 0b0000_0000, - BOOL = 0b0001_0000, - UINT = 0b0010_0000, - NINT = 0b0011_0000, - FLOT = 0b0100_0000, - STRI = 0b1000_0000, - LIST = 0b1011_0000, - BINA = 0b1010_0000, - STRU = 0b1101_0000, - ANNO = 0b1110_0000, -} diff --git a/src/json-pack/ion/symbols.ts b/src/json-pack/ion/symbols.ts deleted file mode 100644 index 59c4c1206d..0000000000 --- a/src/json-pack/ion/symbols.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {Import} from './Import'; -import {SymbolTable} from './types'; - -export const systemSymbolTable: SymbolTable = [ - '$ion', - '$ion_1_0', - '$ion_symbol_table', - 'name', - 'version', - 'imports', - 'symbols', - 'max_id', - '$ion_shared_symbol_table', -]; - -export const systemSymbolImport = new Import(null, systemSymbolTable); diff --git a/src/json-pack/ion/types.ts b/src/json-pack/ion/types.ts deleted file mode 100644 index 1cc84d3a45..0000000000 --- a/src/json-pack/ion/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type SymbolTable = string[]; diff --git a/src/json-pack/json/JsonDecoder.ts b/src/json-pack/json/JsonDecoder.ts deleted file mode 100644 index d595b5359e..0000000000 --- a/src/json-pack/json/JsonDecoder.ts +++ /dev/null @@ -1,683 +0,0 @@ -import {decodeUtf8} from '../../util/buffers/utf8/decodeUtf8'; -import {Reader} from '../../util/buffers/Reader'; -import {fromBase64Bin} from '../../util/base64/fromBase64Bin'; -import {findEndingQuote} from './util'; -import type {BinaryJsonDecoder, PackValue} from '../types'; - -const REGEX_REPLACE_ESCAPED_CHARS = /\\(b|f|n|r|t|"|\/|\\)/g; -const escapedCharReplacer = (char: string) => { - switch (char) { - case '\\b': - return '\b'; - case '\\f': - return '\f'; - case '\\n': - return '\n'; - case '\\r': - return '\r'; - case '\\t': - return '\t'; - case '\\"': - return '"'; - case '\\/': - return '/'; - case '\\\\': - return '\\'; - } - return char; -}; - -// Starts with data:application/octet-stream;base64, - 64 61 74 61 3a 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 2d 73 74 72 65 61 6d 3b 62 61 73 65 36 34 2c -const hasBinaryPrefix = (u8: Uint8Array, x: number) => - u8[x] === 0x64 && - u8[x + 1] === 0x61 && - u8[x + 2] === 0x74 && - u8[x + 3] === 0x61 && - u8[x + 4] === 0x3a && - u8[x + 5] === 0x61 && - u8[x + 6] === 0x70 && - u8[x + 7] === 0x70 && - u8[x + 8] === 0x6c && - u8[x + 9] === 0x69 && - u8[x + 10] === 0x63 && - u8[x + 11] === 0x61 && - u8[x + 12] === 0x74 && - u8[x + 13] === 0x69 && - u8[x + 14] === 0x6f && - u8[x + 15] === 0x6e && - u8[x + 16] === 0x2f && - u8[x + 17] === 0x6f && - u8[x + 18] === 0x63 && - u8[x + 19] === 0x74 && - u8[x + 20] === 0x65 && - u8[x + 21] === 0x74 && - u8[x + 22] === 0x2d && - u8[x + 23] === 0x73 && - u8[x + 24] === 0x74 && - u8[x + 25] === 0x72 && - u8[x + 26] === 0x65 && - u8[x + 27] === 0x61 && - u8[x + 28] === 0x6d && - u8[x + 29] === 0x3b && - u8[x + 30] === 0x62 && - u8[x + 31] === 0x61 && - u8[x + 32] === 0x73 && - u8[x + 33] === 0x65 && - u8[x + 34] === 0x36 && - u8[x + 35] === 0x34 && - u8[x + 36] === 0x2c; - -// Matches "data:application/cbor,base64;9w==" -const isUndefined = (u8: Uint8Array, x: number) => - // u8[x++] === 0x22 && // " - // u8[x++] === 0x64 && // d - u8[x++] === 0x61 && // a - u8[x++] === 0x74 && // t - u8[x++] === 0x61 && // a - u8[x++] === 0x3a && // : - u8[x++] === 0x61 && // a - u8[x++] === 0x70 && // p - u8[x++] === 0x70 && // p - u8[x++] === 0x6c && // l - u8[x++] === 0x69 && // i - u8[x++] === 0x63 && // c - u8[x++] === 0x61 && // a - u8[x++] === 0x74 && // t - u8[x++] === 0x69 && // i - u8[x++] === 0x6f && // o - u8[x++] === 0x6e && // n - u8[x++] === 0x2f && // / - u8[x++] === 0x63 && // c - u8[x++] === 0x62 && // b - u8[x++] === 0x6f && // o - u8[x++] === 0x72 && // r - u8[x++] === 0x2c && // , - u8[x++] === 0x62 && // b - u8[x++] === 0x61 && // a - u8[x++] === 0x73 && // s - u8[x++] === 0x65 && // e - u8[x++] === 0x36 && // 6 - u8[x++] === 0x34 && // 4 - u8[x++] === 0x3b && // ; - u8[x++] === 0x39 && // 9 - u8[x++] === 0x77 && // w - u8[x++] === 0x3d && // = - u8[x++] === 0x3d && // = - u8[x++] === 0x22; // " - -const fromCharCode = String.fromCharCode; - -const readShortUtf8StrAndUnescape = (reader: Reader): string => { - const buf = reader.uint8; - const len = buf.length; - const points: number[] = []; - let x = reader.x; - let prev = 0; - while (x < len) { - let code = buf[x++]!; - if ((code & 0x80) === 0) { - if (prev === 92) { - switch (code) { - case 98: // \b - code = 8; - break; - case 102: // \f - code = 12; - break; - case 110: // \n - code = 10; - break; - case 114: // \r - code = 13; - break; - case 116: // \t - code = 9; - break; - case 34: // \" - code = 34; - break; - case 47: // \/ - code = 47; - break; - case 92: // \\ - code = 92; - break; - default: - throw new Error('Invalid JSON'); - } - prev = 0; - } else { - if (code === 34) break; - prev = code; - if (prev === 92) continue; - } - } else { - const octet2 = buf[x++]! & 0x3f; - if ((code & 0xe0) === 0xc0) { - code = ((code & 0x1f) << 6) | octet2; - } else { - const octet3 = buf[x++]! & 0x3f; - if ((code & 0xf0) === 0xe0) { - code = ((code & 0x1f) << 12) | (octet2 << 6) | octet3; - } else { - if ((code & 0xf8) === 0xf0) { - const octet4 = buf[x++]! & 0x3f; - let unit = ((code & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800; - unit = 0xdc00 | (unit & 0x3ff); - points.push(unit0); - code = unit; - } else { - code = unit; - } - } - } - } - } - points.push(code); - } - reader.x = x; - return fromCharCode.apply(String, points); -}; - -export class JsonDecoder implements BinaryJsonDecoder { - public reader = new Reader(); - - public read(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.readAny(); - } - - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.readAny(); - } - - public readAny(): unknown { - this.skipWhitespace(); - const reader = this.reader; - const x = reader.x; - const uint8 = reader.uint8; - const char = uint8[x]; - switch (char) { - case 34: { - // " - if (uint8[x + 1] === 0x64) { - // d - const bin = this.tryReadBin(); - if (bin) return bin; - if (isUndefined(uint8, x + 2)) { - reader.x = x + 35; - return undefined; - } - } - return this.readStr(); - } - case 91: // [ - return this.readArr(); - case 102: // f - return this.readFalse(); - case 110: // n - return this.readNull(); - case 116: // t - return this.readTrue(); - case 123: // { - return this.readObj(); - default: - if ((char >= 48 && char <= 57) || char === 45) return this.readNum(); - throw new Error('Invalid JSON'); - } - } - - public skipWhitespace(): void { - const reader = this.reader; - const uint8 = reader.uint8; - let x = reader.x; - let char: number = 0; - while (true) { - char = uint8[x]; - switch (char) { - case 32: // space - case 9: // tab - case 10: // line feed - case 13: // carriage return - x++; - continue; - default: - reader.x = x; - return; - } - } - } - - public readNull(): null { - if (this.reader.u32() !== 0x6e756c6c) throw new Error('Invalid JSON'); - return null; - } - - public readTrue(): true { - if (this.reader.u32() !== 0x74727565) throw new Error('Invalid JSON'); - return true; - } - - public readFalse(): false { - const reader = this.reader; - if (reader.u8() !== 0x66 || reader.u32() !== 0x616c7365) throw new Error('Invalid JSON'); - return false; - } - - public readBool(): unknown { - const reader = this.reader; - switch (reader.uint8[reader.x]) { - case 102: // f - return this.readFalse(); - case 116: // t - return this.readTrue(); - default: - throw new Error('Invalid JSON'); - } - } - - public readNum(): number { - const reader = this.reader; - const uint8 = reader.uint8; - let x = reader.x; - let c = uint8[x++]; - const c1 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c2 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c3 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c4 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c5 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c6 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c7 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c8 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c9 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c10 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c11 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c12 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c13 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c14 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c15 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c16 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c17 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c18 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c19 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c20 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode( - c1, - c2, - c3, - c4, - c5, - c6, - c7, - c8, - c9, - c10, - c11, - c12, - c13, - c14, - c15, - c16, - c17, - c18, - c19, - c20, - ); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c21 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode( - c1, - c2, - c3, - c4, - c5, - c6, - c7, - c8, - c9, - c10, - c11, - c12, - c13, - c14, - c15, - c16, - c17, - c18, - c19, - c20, - c21, - ); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c22 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode( - c1, - c2, - c3, - c4, - c5, - c6, - c7, - c8, - c9, - c10, - c11, - c12, - c13, - c14, - c15, - c16, - c17, - c18, - c19, - c20, - c21, - c22, - ); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c23 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode( - c1, - c2, - c3, - c4, - c5, - c6, - c7, - c8, - c9, - c10, - c11, - c12, - c13, - c14, - c15, - c16, - c17, - c18, - c19, - c20, - c21, - c22, - c23, - ); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - const c24 = c; - c = uint8[x++]; - if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) { - reader.x = x - 1; - const num = +fromCharCode( - c1, - c2, - c3, - c4, - c5, - c6, - c7, - c8, - c9, - c10, - c11, - c12, - c13, - c14, - c15, - c16, - c17, - c18, - c19, - c20, - c21, - c22, - c24, - ); - if (num !== num) throw new Error('Invalid JSON'); - return num; - } - throw new Error('Invalid JSON'); - } - - public readStr(): string { - const reader = this.reader; - const uint8 = reader.uint8; - const char = uint8[reader.x++]; - if (char !== 0x22) throw new Error('Invalid JSON'); - const x0 = reader.x; - const x1 = findEndingQuote(uint8, x0); - let str = decodeUtf8(uint8, x0, x1 - x0); - /** @todo perf: maybe faster is to first check if there are any escaped chars. */ - str = str.replace(REGEX_REPLACE_ESCAPED_CHARS, escapedCharReplacer); - reader.x = x1 + 1; - return str; - } - - public tryReadBin(): Uint8Array | undefined { - const reader = this.reader; - const u8 = reader.uint8; - let x = reader.x; - if (u8[x++] !== 0x22) return undefined; - const hasDataUrlPrefix = hasBinaryPrefix(u8, x); - if (!hasDataUrlPrefix) return undefined; - x += 37; - const x0 = x; - x = findEndingQuote(u8, x); - reader.x = x0; - const bin = fromBase64Bin(reader.view, x0, x - x0); - reader.x = x + 1; - return bin; - } - - public readBin(): Uint8Array { - const reader = this.reader; - const u8 = reader.uint8; - let x = reader.x; - if (u8[x++] !== 0x22) throw new Error('Invalid JSON'); - const hasDataUrlPrefix = hasBinaryPrefix(u8, x); - if (!hasDataUrlPrefix) throw new Error('Invalid JSON'); - x += 37; - const x0 = x; - x = findEndingQuote(u8, x); - reader.x = x0; - const bin = fromBase64Bin(reader.view, x0, x - x0); - reader.x = x + 1; - return bin; - } - - public readArr(): unknown[] { - const reader = this.reader; - if (reader.u8() !== 0x5b) throw new Error('Invalid JSON'); - const arr: unknown[] = []; - const uint8 = reader.uint8; - while (true) { - this.skipWhitespace(); - const char = uint8[reader.x]; - if (char === 0x5d) return reader.x++, arr; // ] - if (char === 0x2c) { - reader.x++; - continue; - } // , - arr.push(this.readAny()); - } - } - - public readObj(): PackValue | Record | unknown { - const reader = this.reader; - if (reader.u8() !== 0x7b) throw new Error('Invalid JSON'); - const obj: Record = {}; - const uint8 = reader.uint8; - while (true) { - this.skipWhitespace(); - let char = uint8[reader.x]; - if (char === 0x7d) return reader.x++, obj; // } - if (char === 0x2c) { - reader.x++; - continue; - } // , - char = uint8[reader.x++]; - if (char !== 0x22) throw new Error('Invalid JSON'); - const key = readShortUtf8StrAndUnescape(reader); - if (key === '__proto__') throw new Error('Invalid JSON'); - this.skipWhitespace(); - if (reader.u8() !== 0x3a) throw new Error('Invalid JSON'); - this.skipWhitespace(); - obj[key] = this.readAny(); - } - } -} diff --git a/src/json-pack/json/JsonDecoderDag.ts b/src/json-pack/json/JsonDecoderDag.ts deleted file mode 100644 index 0735810f2e..0000000000 --- a/src/json-pack/json/JsonDecoderDag.ts +++ /dev/null @@ -1,133 +0,0 @@ -import {JsonDecoder} from './JsonDecoder'; -import {findEndingQuote} from './util'; -import type {PackValue} from '../types'; -import {createFromBase64Bin} from '../../util/base64/createFromBase64Bin'; - -export const fromBase64Bin = createFromBase64Bin(undefined, ''); - -export class JsonDecoderDag extends JsonDecoder { - public readObj(): PackValue | Record | Uint8Array | unknown { - const bytes = this.tryReadBytes(); - if (bytes) return bytes; - const cid = this.tryReadCid(); - if (cid) return cid; - return super.readObj(); - } - - protected tryReadBytes(): Uint8Array | undefined { - const reader = this.reader; - const x = reader.x; - if (reader.u8() !== 0x7b) { - // { - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x22 || reader.u8() !== 0x2f || reader.u8() !== 0x22) { - // "/" - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x3a) { - // : - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x7b) { - // { - reader.x = x; - return; - } - this.skipWhitespace(); - if ( - reader.u8() !== 0x22 || - reader.u8() !== 0x62 || - reader.u8() !== 0x79 || - reader.u8() !== 0x74 || - reader.u8() !== 0x65 || - reader.u8() !== 0x73 || - reader.u8() !== 0x22 - ) { - // "bytes" - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x3a) { - // : - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x22) { - // " - reader.x = x; - return; - } - const bufStart = reader.x; - const bufEnd = findEndingQuote(reader.uint8, bufStart); - reader.x = 1 + bufEnd; - this.skipWhitespace(); - if (reader.u8() !== 0x7d) { - // } - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x7d) { - // } - reader.x = x; - return; - } - const bin = fromBase64Bin(reader.view, bufStart, bufEnd - bufStart); - return bin; - } - - protected tryReadCid(): undefined | unknown { - const reader = this.reader; - const x = reader.x; - if (reader.u8() !== 0x7b) { - // { - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x22 || reader.u8() !== 0x2f || reader.u8() !== 0x22) { - // "/" - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x3a) { - // : - reader.x = x; - return; - } - this.skipWhitespace(); - if (reader.u8() !== 0x22) { - // " - reader.x = x; - return; - } - const bufStart = reader.x; - const bufEnd = findEndingQuote(reader.uint8, bufStart); - reader.x = 1 + bufEnd; - this.skipWhitespace(); - if (reader.u8() !== 0x7d) { - // } - reader.x = x; - return; - } - const finalX = reader.x; - reader.x = bufStart; - const cid = reader.ascii(bufEnd - bufStart); - reader.x = finalX; - return this.readCid(cid); - } - - public readCid(cid: string): unknown { - return cid; - } -} diff --git a/src/json-pack/json/JsonEncoder.ts b/src/json-pack/json/JsonEncoder.ts deleted file mode 100644 index a57566005a..0000000000 --- a/src/json-pack/json/JsonEncoder.ts +++ /dev/null @@ -1,282 +0,0 @@ -import {toBase64Bin} from '../../util/base64/toBase64Bin'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder, StreamingBinaryJsonEncoder} from '../types'; - -export class JsonEncoder implements BinaryJsonEncoder, StreamingBinaryJsonEncoder { - constructor(public readonly writer: IWriter & IWriterGrowable) {} - - public encode(value: unknown): Uint8Array { - const writer = this.writer; - writer.reset(); - this.writeAny(value); - return writer.flush(); - } - - /** - * Called when the encoder encounters a value that it does not know how to encode. - * - * @param value Some JavaScript value. - */ - public writeUnknown(value: unknown): void { - this.writeNull(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'boolean': - return this.writeBoolean(value); - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'object': { - if (value === null) return this.writeNull(); - const constructor = value.constructor; - switch (constructor) { - case Object: - return this.writeObj(value as Record); - case Array: - return this.writeArr(value as unknown[]); - case Uint8Array: - return this.writeBin(value as Uint8Array); - default: - return this.writeUnknown(value); - } - } - case 'undefined': { - return this.writeUndef(); - } - default: - return this.writeUnknown(value); - } - } - - public writeNull(): void { - this.writer.u32(0x6e756c6c); // null - } - - public writeUndef(): void { - const writer = this.writer; - const length = 35; - writer.ensureCapacity(length); - // Write: "data:application/cbor,base64;9w==" - const view = writer.view; - let x = writer.x; - view.setUint32(x, 0x22_64_61_74); // "dat - x += 4; - view.setUint32(x, 0x61_3a_61_70); // a:ap - x += 4; - view.setUint32(x, 0x70_6c_69_63); // plic - x += 4; - view.setUint32(x, 0x61_74_69_6f); // atio - x += 4; - view.setUint32(x, 0x6e_2f_63_62); // n/cb - x += 4; - view.setUint32(x, 0x6f_72_2c_62); // or,b - x += 4; - view.setUint32(x, 0x61_73_65_36); // ase6 - x += 4; - view.setUint32(x, 0x34_3b_39_77); // 4;9w - x += 4; - view.setUint16(x, 0x3d_3d); // == - x += 2; - writer.uint8[x++] = 0x22; // " - writer.x = x; - } - - public writeBoolean(bool: boolean): void { - if (bool) - this.writer.u32(0x74727565); // true - else this.writer.u8u32(0x66, 0x616c7365); // false - } - - public writeNumber(num: number): void { - const str = num.toString(); - this.writer.ascii(str); - } - - public writeInteger(int: number): void { - this.writeNumber(int >> 0 === int ? int : Math.trunc(int)); - } - - public writeUInteger(uint: number): void { - this.writeInteger(uint < 0 ? -uint : uint); - } - - public writeFloat(float: number): void { - this.writeNumber(float); - } - - public writeBin(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.ensureCapacity(38 + 3 + (length << 1)); - // Write: "data:application/octet-stream;base64, - 22 64 61 74 61 3a 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6f 63 74 65 74 2d 73 74 72 65 61 6d 3b 62 61 73 65 36 34 2c - const view = writer.view; - let x = writer.x; - view.setUint32(x, 0x22_64_61_74); // "dat - x += 4; - view.setUint32(x, 0x61_3a_61_70); // a:ap - x += 4; - view.setUint32(x, 0x70_6c_69_63); // plic - x += 4; - view.setUint32(x, 0x61_74_69_6f); // atio - x += 4; - view.setUint32(x, 0x6e_2f_6f_63); // n/oc - x += 4; - view.setUint32(x, 0x74_65_74_2d); // tet- - x += 4; - view.setUint32(x, 0x73_74_72_65); // stre - x += 4; - view.setUint32(x, 0x61_6d_3b_62); // am;b - x += 4; - view.setUint32(x, 0x61_73_65_36); // ase6 - x += 4; - view.setUint16(x, 0x34_2c); // 4, - x += 2; - x = toBase64Bin(buf, 0, length, view, x); - writer.uint8[x++] = 0x22; // " - writer.x = x; - } - - public writeStr(str: string): void { - const writer = this.writer; - const length = str.length; - writer.ensureCapacity(length * 4 + 2); - if (length < 256) { - let x = writer.x; - const uint8 = writer.uint8; - uint8[x++] = 0x22; // " - for (let i = 0; i < length; i++) { - const code = str.charCodeAt(i); - switch (code) { - case 34: // " - case 92: // \ - uint8[x++] = 0x5c; // \ - break; - } - if (code < 32 || code > 126) { - writer.utf8(JSON.stringify(str)); - return; - } else uint8[x++] = code; - } - uint8[x++] = 0x22; // " - writer.x = x; - return; - } - writer.utf8(JSON.stringify(str)); - } - - public writeAsciiStr(str: string): void { - const length = str.length; - const writer = this.writer; - writer.ensureCapacity(length * 2 + 2); - const uint8 = writer.uint8; - let x = writer.x; - uint8[x++] = 0x22; // " - for (let i = 0; i < length; i++) { - const code = str.charCodeAt(i); - switch (code) { - case 34: // " - case 92: // \ - uint8[x++] = 0x5c; // \ - break; - } - uint8[x++] = code; - } - uint8[x++] = 0x22; // " - writer.x = x; - } - - public writeArr(arr: unknown[]): void { - const writer = this.writer; - writer.u8(0x5b); // [ - const length = arr.length; - const last = length - 1; - for (let i = 0; i < last; i++) { - this.writeAny(arr[i]); - writer.u8(0x2c); // , - } - if (last >= 0) this.writeAny(arr[last]); - writer.u8(0x5d); // ] - } - - public writeArrSeparator(): void { - this.writer.u8(0x2c); // , - } - - public writeObj(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - const length = keys.length; - if (!length) return writer.u16(0x7b7d); // {} - writer.u8(0x7b); // { - for (let i = 0; i < length; i++) { - const key = keys[i]; - const value = obj[key]; - this.writeStr(key); - writer.u8(0x3a); // : - this.writeAny(value); - writer.u8(0x2c); // , - } - writer.uint8[writer.x - 1] = 0x7d; // } - } - - public writeObjSeparator(): void { - this.writer.u8(0x2c); // , - } - - public writeObjKeySeparator(): void { - this.writer.u8(0x3a); // : - } - - // ------------------------------------------------------- Streaming encoding - - public writeStartStr(): void { - throw new Error('Method not implemented.'); - } - - public writeStrChunk(str: string): void { - throw new Error('Method not implemented.'); - } - - public writeEndStr(): void { - throw new Error('Method not implemented.'); - } - - public writeStartBin(): void { - throw new Error('Method not implemented.'); - } - - public writeBinChunk(buf: Uint8Array): void { - throw new Error('Method not implemented.'); - } - - public writeEndBin(): void { - throw new Error('Method not implemented.'); - } - - public writeStartArr(): void { - this.writer.u8(0x5b); // [ - } - - public writeArrChunk(item: unknown): void { - throw new Error('Method not implemented.'); - } - - public writeEndArr(): void { - this.writer.u8(0x5d); // ] - } - - public writeStartObj(): void { - this.writer.u8(0x7b); // { - } - - public writeObjChunk(key: string, value: unknown): void { - throw new Error('Method not implemented.'); - } - - public writeEndObj(): void { - this.writer.u8(0x7d); // } - } -} diff --git a/src/json-pack/json/JsonEncoderDag.ts b/src/json-pack/json/JsonEncoderDag.ts deleted file mode 100644 index 3c7dd4f51b..0000000000 --- a/src/json-pack/json/JsonEncoderDag.ts +++ /dev/null @@ -1,59 +0,0 @@ -import {JsonEncoderStable} from './JsonEncoderStable'; -import {createToBase64Bin} from '../../util/base64/createToBase64Bin'; - -const objBaseLength = '{"/":{"bytes":""}}'.length; -const cidBaseLength = '{"/":""}'.length; -const base64Encode = createToBase64Bin(undefined, ''); - -/** - * Base class for implementing DAG-JSON encoders. - * - * @see https://ipld.io/specs/codecs/dag-json/spec/ - */ -export class JsonEncoderDag extends JsonEncoderStable { - /** - * Encodes binary data as nested `["/", "bytes"]` object encoded in Base64 - * without padding. - * - * Example: - * - * ```json - * {"/":{"bytes":"aGVsbG8gd29ybGQ"}} - * ``` - * - * @param buf Binary data to write. - */ - public writeBin(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.ensureCapacity(objBaseLength + (length << 1)); - const view = writer.view; - const uint8 = writer.uint8; - let x = writer.x; - view.setUint32(x, 0x7b222f22); // {"/" - x += 4; - view.setUint32(x, 0x3a7b2262); // :{"b - x += 4; - view.setUint32(x, 0x79746573); // ytes - x += 4; - view.setUint16(x, 0x223a); // ": - x += 2; - uint8[x] = 0x22; // " - x += 1; - x = base64Encode(buf, 0, length, view, x); - view.setUint16(x, 0x227d); // "} - x += 2; - uint8[x] = 0x7d; // } - x += 1; - writer.x = x; - } - - public writeCid(cid: string): void { - const writer = this.writer; - writer.ensureCapacity(cidBaseLength + cid.length); - writer.u32(0x7b222f22); // {"/" - writer.u16(0x3a22); // :" - writer.ascii(cid); - writer.u16(0x227d); // "} - } -} diff --git a/src/json-pack/json/JsonEncoderStable.ts b/src/json-pack/json/JsonEncoderStable.ts deleted file mode 100644 index 203d07dcdf..0000000000 --- a/src/json-pack/json/JsonEncoderStable.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {JsonEncoder} from './JsonEncoder'; -import {sort} from '../../util/sort/insertion2'; -import {objKeyCmp} from '../util/objKeyCmp'; - -export class JsonEncoderStable extends JsonEncoder { - public writeObj(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - sort(keys, objKeyCmp); - const length = keys.length; - if (!length) return writer.u16(0x7b7d); // {} - writer.u8(0x7b); // { - for (let i = 0; i < length; i++) { - const key = keys[i]; - const value = obj[key]; - this.writeStr(key); - writer.u8(0x3a); // : - this.writeAny(value); - writer.u8(0x2c); // , - } - writer.uint8[writer.x - 1] = 0x7d; // } - } -} diff --git a/src/json-pack/json/README.md b/src/json-pack/json/README.md deleted file mode 100644 index 77066c669b..0000000000 --- a/src/json-pack/json/README.md +++ /dev/null @@ -1,117 +0,0 @@ -## Benchmarks - -Encoding: - -``` -npx ts-node benchmarks/json-pack/bench.json.encoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Small object, 44 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 5,800,937 ops/sec ±0.90% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 2,220,449 ops/sec ±0.71% (97 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 1,998,965 ops/sec ±0.68% (96 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 1,396,750 ops/sec ±0.80% (99 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() -------------------------------------------------------------------------- Typical object, 993 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 320,862 ops/sec ±1.81% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 214,464 ops/sec ±0.49% (100 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 187,439 ops/sec ±0.68% (97 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 119,426 ops/sec ±1.93% (93 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() --------------------------------------------------------------------------- Large object, 3741 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 87,901 ops/sec ±1.22% (95 runs sampled) -👍 Buffer.from(JSON.stringify()) x 65,695 ops/sec ±1.06% (96 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 56,424 ops/sec ±1.80% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 38,689 ops/sec ±1.77% (96 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() --------------------------------------------------------------------- Very large object, 45750 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 6,087 ops/sec ±0.45% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 6,094 ops/sec ±0.21% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 4,133 ops/sec ±0.97% (98 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 1,813 ops/sec ±0.26% (99 runs sampled) -Fastest is 👍 Buffer.from(JSON.stringify()),👍 json-joy/json-pack JsonEncoder.encode() ------------------------------------------------------------------- Object with many keys, 969 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 251,763 ops/sec ±0.65% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 194,535 ops/sec ±0.13% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 154,017 ops/sec ±0.15% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 64,720 ops/sec ±0.13% (98 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() -------------------------------------------------------------------------- String ladder, 3398 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 146,873 ops/sec ±0.44% (99 runs sampled) -👍 Buffer.from(JSON.stringify()) x 127,235 ops/sec ±0.46% (93 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 126,412 ops/sec ±0.10% (101 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 126,018 ops/sec ±0.21% (101 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() --------------------------------------------------------------------------- Long strings, 7011 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 50,734 ops/sec ±0.10% (99 runs sampled) -👍 Buffer.from(JSON.stringify()) x 29,757 ops/sec ±0.32% (100 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 29,607 ops/sec ±0.43% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 29,563 ops/sec ±0.59% (97 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() --------------------------------------------------------------------------- Short strings, 170 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 1,597,067 ops/sec ±0.14% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 979,318 ops/sec ±1.18% (99 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 826,713 ops/sec ±1.74% (93 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 815,531 ops/sec ±3.65% (87 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() --------------------------------------------------------------------------------- Numbers, 136 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 1,382,467 ops/sec ±4.90% (78 runs sampled) -👍 Buffer.from(JSON.stringify()) x 1,009,130 ops/sec ±1.66% (91 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 821,214 ops/sec ±4.36% (88 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 886,689 ops/sec ±0.33% (99 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() ---------------------------------------------------------------------------------- Tokens, 308 bytes -👍 json-joy/json-pack JsonEncoder.encode() x 1,357,017 ops/sec ±0.38% (98 runs sampled) -👍 Buffer.from(JSON.stringify()) x 965,756 ops/sec ±0.19% (93 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify()) x 648,336 ops/sec ±0.45% (96 runs sampled) -👍 fast-safe-stringify + Buffer.from(safeStringify.stableStringify()) x 642,934 ops/sec ±0.34% (97 runs sampled) -Fastest is 👍 json-joy/json-pack JsonEncoder.encode() -``` - -Decoding: - -``` -npx ts-node benchmarks/json-pack/bench.json.decoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 ---------------------------------------------------------------------------- Small object, 175 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 1,149,110 ops/sec ±0.16% (99 runs sampled) -👍 Native JSON.parse(buf.toString()) x 2,360,476 ops/sec ±0.56% (94 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) ------------------------------------------------------------------------- Typical object, 3587 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 86,604 ops/sec ±0.56% (98 runs sampled) -👍 Native JSON.parse(buf.toString()) x 245,029 ops/sec ±1.28% (98 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) -------------------------------------------------------------------------- Large object, 13308 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 25,911 ops/sec ±0.64% (102 runs sampled) -👍 Native JSON.parse(buf.toString()) x 67,049 ops/sec ±0.15% (100 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) -------------------------------------------------------------------- Very large object, 162796 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 1,494 ops/sec ±0.32% (100 runs sampled) -👍 Native JSON.parse(buf.toString()) x 3,557 ops/sec ±0.33% (100 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) ------------------------------------------------------------------ Object with many keys, 3339 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 47,767 ops/sec ±0.90% (100 runs sampled) -👍 Native JSON.parse(buf.toString()) x 280,836 ops/sec ±2.21% (94 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) ------------------------------------------------------------------------- String ladder, 13302 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 60,041 ops/sec ±1.26% (94 runs sampled) -👍 Native JSON.parse(buf.toString()) x 317,991 ops/sec ±1.08% (98 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) -------------------------------------------------------------------------- Long strings, 30251 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 37,350 ops/sec ±0.76% (98 runs sampled) -👍 Native JSON.parse(buf.toString()) x 44,679 ops/sec ±0.40% (97 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) --------------------------------------------------------------------------- Short strings, 625 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 311,662 ops/sec ±0.59% (97 runs sampled) -👍 Native JSON.parse(buf.toString()) x 1,131,918 ops/sec ±1.40% (97 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) --------------------------------------------------------------------------------- Numbers, 434 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 631,451 ops/sec ±0.23% (99 runs sampled) -👍 Native JSON.parse(buf.toString()) x 1,815,177 ops/sec ±0.55% (94 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) --------------------------------------------------------------------------------- Tokens, 1182 bytes -👍 json-joy/json-pack JsonDecoder.decode() x 1,312,357 ops/sec ±0.55% (99 runs sampled) -👍 Native JSON.parse(buf.toString()) x 1,385,641 ops/sec ±2.35% (94 runs sampled) -Fastest is 👍 Native JSON.parse(buf.toString()) -``` diff --git a/src/json-pack/json/__tests__/JsonDecoder.spec.ts b/src/json-pack/json/__tests__/JsonDecoder.spec.ts deleted file mode 100644 index d8946a6a42..0000000000 --- a/src/json-pack/json/__tests__/JsonDecoder.spec.ts +++ /dev/null @@ -1,440 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonDecoder} from '../JsonDecoder'; -import {JsonEncoder} from '../JsonEncoder'; - -const decoder = new JsonDecoder(); - -describe('null', () => { - test('null', () => { - const data = Buffer.from('null', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(null); - }); - - test('null with whitespace', () => { - const data = Buffer.from(' null', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(null); - }); - - test('null with more whitespace', () => { - const data = Buffer.from(' \n\n \n \t \r \r null \r \r \r\t\n', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(null); - }); -}); - -describe('undefined', () => { - test('undefined', () => { - const encoder = new JsonEncoder(new Writer()); - const encoded = encoder.encode(undefined); - const decoded = decoder.read(encoded); - expect(decoded).toBe(undefined); - }); - - test('undefined in array', () => { - const encoder = new JsonEncoder(new Writer()); - const encoded = encoder.encode({foo: [1, undefined, -1]}); - const decoded = decoder.read(encoded); - expect(decoded).toEqual({foo: [1, undefined, -1]}); - }); -}); - -describe('boolean', () => { - test('true', () => { - const data = Buffer.from('true', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(true); - }); - - test('true with whitespace', () => { - const data = Buffer.from('\n \t \r true\n \t \r ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(true); - }); - - test('false', () => { - const data = Buffer.from('false', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(false); - }); - - test('true with whitespace', () => { - const data = Buffer.from('\n \t \r false\n \t \r ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(false); - }); - - test('can read any boolean - 1', () => { - const data = Buffer.from('\n \t \r false\n \t \r ', 'utf-8'); - decoder.reader.reset(data); - decoder.skipWhitespace(); - const value = decoder.readBool(); - expect(value).toBe(false); - }); - - test('can read any boolean - 2', () => { - const data = Buffer.from('true ', 'utf-8'); - decoder.reader.reset(data); - decoder.skipWhitespace(); - const value = decoder.readBool(); - expect(value).toBe(true); - }); -}); - -describe('number', () => { - test('1', () => { - const data = Buffer.from('1', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(1); - }); - - test('12', () => { - const data = Buffer.from('12', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(12); - }); - - test('123', () => { - const data = Buffer.from('123', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(123); - }); - - test('1234', () => { - const data = Buffer.from('1234', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(1234); - }); - - test('12345', () => { - const data = Buffer.from('12345', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(12345); - }); - - test('123456', () => { - const data = Buffer.from('123456', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(123456); - }); - - test('-0.1234', () => { - const data = Buffer.from('-0.1234', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(-0.1234); - }); - - test('3n', () => { - const data = Buffer.from('3n', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(3); - }); - - test('with whitespace', () => { - const data = Buffer.from('\n \r 5.6 ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(5.6); - }); -}); - -describe('string', () => { - test('empty string', () => { - const data = Buffer.from('""', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(''); - }); - - test('empty string with whitespace', () => { - const data = Buffer.from(' \n \r \t "" \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(''); - }); - - test('one char string', () => { - const data = Buffer.from('"a"', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe('a'); - }); - - test('"hello world" string', () => { - const data = Buffer.from('"hello world"', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe('hello world'); - }); - - test('string with emoji', () => { - const str = 'yes! - 👍🏻👍🏼👍🏽👍🏾👍🏿'; - const data = Buffer.from(' "yes! - 👍🏻👍🏼👍🏽👍🏾👍🏿" ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('string with quote', () => { - const str = 'this is a "quote"'; - const data = Buffer.from(JSON.stringify(str), 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('string with new line', () => { - const str = 'this is a \n new line'; - const json = JSON.stringify(str); - const data = Buffer.from(json, 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('string with backslash', () => { - const str = 'this is a \\ backslash'; - const json = JSON.stringify(str); - const data = Buffer.from(json, 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('a single backslash character', () => { - const str = '\\'; - const json = JSON.stringify(str); - const data = Buffer.from(json, 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('string with tab', () => { - const str = 'this is a \t tab'; - const json = JSON.stringify(str); - const data = Buffer.from(json, 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe(str); - }); - - test('string unicode characters', () => { - const json = '"15\u00f8C"'; - const data = Buffer.from(json, 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toBe('15\u00f8C'); - }); -}); - -describe('binary', () => { - test('empty buffer', () => { - const encoder = new JsonEncoder(new Writer()); - const data = encoder.encode(new Uint8Array(0)); - decoder.reader.reset(data); - const value1 = decoder.readAny(); - expect(value1).toEqual(new Uint8Array(0)); - decoder.reader.reset(data); - const value2 = decoder.readBin(); - expect(value2).toEqual(new Uint8Array(0)); - }); - - test('a small buffer', () => { - const encoder = new JsonEncoder(new Writer()); - const data = encoder.encode(new Uint8Array([4, 5, 6])); - decoder.reader.reset(data); - const value = decoder.readBin(); - expect(value).toEqual(new Uint8Array([4, 5, 6])); - }); -}); - -describe('array', () => { - test('empty array', () => { - const data = Buffer.from('[]', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([]); - }); - - test('empty array with whitespace', () => { - const data = Buffer.from(' \n \r \t [] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([]); - }); - - test('array with one number element', () => { - const data = Buffer.from(' \n \r \t [1] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([1]); - }); - - test('array with one number element - 2', () => { - const data = Buffer.from(' \n \r \t [ -3.5e2\n] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([-3.5e2]); - }); - - test('array with one boolean', () => { - const data = Buffer.from(' \n \r \t [ true] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([true]); - }); - - test('array with one boolean - 2', () => { - const data = Buffer.from(' \n \r \t [false ] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([false]); - }); - - test('array with one null', () => { - const data = Buffer.from(' \n \r \t [null] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([null]); - }); - - test('array with multiple numbers', () => { - const data = Buffer.from(' \n \r \t [1, 2.2,-3.3 ] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([1, 2.2, -3.3]); - }); - - test('nested arrays', () => { - const data = Buffer.from(' \n \r \t [[],\n[ 4,\t5] , [null]] \n \r \t ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual([[], [4, 5], [null]]); - }); - - test('array with strings', () => { - const data = Buffer.from('["a", ["b"], "c", ["d", "e"], [ ] ]', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(['a', ['b'], 'c', ['d', 'e'], []]); - }); -}); - -describe('object', () => { - test('empty object', () => { - const data = Buffer.from('{}', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({}); - }); - - test('empty object with whitespace', () => { - const data = Buffer.from(' { } ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({}); - }); - - test('empty object with whitespace - 2', () => { - const data = Buffer.from(' {\n} ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({}); - }); - - test('object with single key', () => { - const data = Buffer.from(' { "foo" : "bar" } ', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({foo: 'bar'}); - }); - - test('nested object', () => { - const data = Buffer.from('{"":{}}', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({'': {}}); - }); - - test('nested object', () => { - const data = Buffer.from('{"":{}}', 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual({'': {}}); - }); - - test('complex nested object', () => { - const obj = { - a: 1, - b: true, - c: null, - d: [1, 2, 3], - e: { - f: 'foo', - g: 'bar', - h: { - i: 'baz', - j: 'qux', - }, - }, - }; - const data = Buffer.from(JSON.stringify(obj), 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(obj); - }); - - test('complex nested object - 2', () => { - const obj = { - '!Cq"G_f/]j': 'pG.HEFjh', - '<3-': [285717617.40402037, '! qiH14NE', 'YCu"<>)PWv[9ot', 591097389.6547585], - 'zJ49L}1A)M]': { - 'V0`*ei?8E': { - 'C8:yy': -2807878070964447, - '$^': 855760508.2633594, - 'ew5!f{>w/B zg': 'vGS', - 'oFaFl,&F{9J9!=h': 828843580.1490843, - }, - '5|': { - '?#^5`_ABY"': ["h'mHT-\\JK\\$", 'je{O<3l(', 'q'], - 'Z|gPbq,LZB9^$].8': ['mo"Ho'], - Sl45: 796047966.3180537, - "`_pz@ADh 'iYlc5V": 1128283461473140, - }, - 'y|#.;\\QpUx8T': -53172, - 'BGk-f#QZ_!)2Tup4': 87540156.63740477, - 'H5tl@md|9(-': 411281070.2708618, - }, - 'XH>)': 718476139.1743257, - 't$@`w': { - 'jQ$1y"9': null, - 诶г西诶必西诶西西诶诶西西: 64094888.57050705, - }, - 'OWB@6%': "'bx8Fc", - '#vxKbXgF+$mIk': 919164616.3711811, - 'x!UZa*e@Rfz': '\\', - "tyae=ID>')Z5Bu?": 721968011.7405405, - }; - const data = Buffer.from(JSON.stringify(obj), 'utf-8'); - decoder.reader.reset(data); - const value = decoder.readAny(); - expect(value).toEqual(obj); - }); -}); diff --git a/src/json-pack/json/__tests__/JsonDecoderDag.spec.ts b/src/json-pack/json/__tests__/JsonDecoderDag.spec.ts deleted file mode 100644 index a0a8f7adbc..0000000000 --- a/src/json-pack/json/__tests__/JsonDecoderDag.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {utf8} from '../../../util/buffers/strings'; -import {JsonEncoderDag} from '../JsonEncoderDag'; -import {JsonDecoderDag} from '../JsonDecoderDag'; - -const writer = new Writer(16); -const encoder = new JsonEncoderDag(writer); -const decoder = new JsonDecoderDag(); - -describe('Bytes', () => { - test('can decode a simple buffer in object', () => { - const buf = utf8`hello world`; - const data = {foo: buf}; - const encoded = encoder.encode(data); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(data); - }); - - test('can decode buffers inside an array', () => { - const data = [0, utf8``, utf8`asdf`, 1]; - const encoded = encoder.encode(data); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(data); - }); - - test('can decode buffer with whitespace surrounding literals', () => { - const json = ' { "foo" : { "/" : { "bytes" : "aGVsbG8gd29ybGQ" } } } '; - const encoded = Buffer.from(json); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual({foo: utf8`hello world`}); - }); -}); - -describe('Cid', () => { - class CID { - constructor(public readonly value: string) {} - } - - class IpfsEncoder extends JsonEncoderDag { - public writeUnknown(value: unknown): void { - if (value instanceof CID) return this.writeCid(value.value); - else super.writeUnknown(value); - } - } - - class IpfsDecoder extends JsonDecoderDag { - public readCid(cid: string): unknown { - return new CID(cid); - } - } - - const encoder = new IpfsEncoder(writer); - const decoder = new IpfsDecoder(); - - test('can decode a single CID', () => { - const data = new CID('Qm'); - const encoded = encoder.encode(data); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(data); - }); - - test('can decode a CID in object and array', () => { - const data = { - foo: 'bar', - baz: new CID('Qm'), - qux: [new CID('bu'), 'quux'], - }; - const encoded = encoder.encode(data); - const decoded = decoder.decode(encoded); - expect(decoded).toEqual(data); - }); -}); diff --git a/src/json-pack/json/__tests__/JsonEncoder.spec.ts b/src/json-pack/json/__tests__/JsonEncoder.spec.ts deleted file mode 100644 index 3c5d031b83..0000000000 --- a/src/json-pack/json/__tests__/JsonEncoder.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {JsonEncoder} from '../JsonEncoder'; - -const writer = new Writer(16); -const encoder = new JsonEncoder(writer); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - const json = Buffer.from(encoded).toString('utf-8'); - // console.log('json', json); - const decoded = JSON.parse(json); - expect(decoded).toEqual(value); -}; - -describe('null', () => { - test('null', () => { - assertEncoder(null); - }); -}); - -describe('undefined', () => { - test('undefined', () => { - const encoded = encoder.encode(undefined); - const txt = Buffer.from(encoded).toString('utf-8'); - expect(txt).toBe('"data:application/cbor,base64;9w=="'); - }); - - test('undefined in object', () => { - const encoded = encoder.encode({foo: undefined}); - const txt = Buffer.from(encoded).toString('utf-8'); - expect(txt).toBe('{"foo":"data:application/cbor,base64;9w=="}'); - }); -}); - -describe('boolean', () => { - test('true', () => { - assertEncoder(true); - }); - - test('false', () => { - assertEncoder(false); - }); -}); - -describe('number', () => { - test('integers', () => { - assertEncoder(0); - assertEncoder(1); - assertEncoder(-1); - assertEncoder(123); - assertEncoder(-123); - assertEncoder(-12321321123); - assertEncoder(+2321321123); - }); - - test('floats', () => { - assertEncoder(0.0); - assertEncoder(1.1); - assertEncoder(-1.45); - assertEncoder(123.34); - assertEncoder(-123.234); - assertEncoder(-12321.321123); - assertEncoder(+2321321.123); - }); -}); - -describe('string', () => { - test('empty string', () => { - assertEncoder(''); - }); - - test('one char strings', () => { - assertEncoder('a'); - assertEncoder('b'); - assertEncoder('z'); - assertEncoder('~'); - assertEncoder('"'); - assertEncoder('\\'); - assertEncoder('*'); - assertEncoder('@'); - assertEncoder('9'); - assertEncoder('✅'); - assertEncoder('👍'); - }); - - test('short strings', () => { - assertEncoder('abc'); - assertEncoder('abc123'); - }); - - test('long strings', () => { - assertEncoder( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.', - ); - }); - - test('unsafe character in the middle of a string', () => { - assertEncoder('...................".....................'); - }); - - test('unsafe character in the middle of a string - 2', () => { - assertEncoder('...................🎉.....................'); - }); -}); - -describe('array', () => { - test('empty array', () => { - assertEncoder([]); - }); - - test('array with one element', () => { - assertEncoder([1]); - }); - - test('array with two elements', () => { - assertEncoder([1, 2]); - }); - - test('array of array', () => { - assertEncoder([[123]]); - }); - - test('array of various types', () => { - assertEncoder([0, 1.32, 'str', true, false, null, [1, 2, 3]]); - }); -}); - -describe('object', () => { - test('empty object', () => { - assertEncoder({}); - }); - - test('object with one key', () => { - assertEncoder({foo: 'bar'}); - }); - - test('object with two keys', () => { - assertEncoder({foo: 'bar', baz: 123}); - }); - - test('object with various nested types', () => { - assertEncoder({ - '': null, - null: false, - true: true, - str: 'asdfasdf ,asdf asdf asdf asdf asdf, asdflkasjdflakjsdflajskdlfkasdf', - num: 123, - arr: [1, 2, 3], - obj: {foo: 'bar'}, - obj2: {1: 2, 3: 4}, - }); - }); -}); - -describe('nested object', () => { - test('large array/object', () => { - assertEncoder({ - foo: [ - 1, - 2, - 3, - { - looongLoooonnnngggg: 'bar', - looongLoooonnnngggg2: 'bar', - looongLoooonnnngggg3: 'bar', - looongLoooonnnngggg4: 'bar', - looongLoooonnnngggg5: 'bar', - looongLoooonnnngggg6: 'bar', - looongLoooonnnngggg7: 'bar', - someVeryVeryLongKeyNameSuperDuperLongKeyName: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName1: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName2: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName3: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName4: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName5: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName6: 'very very long value, I said, very very long value', - }, - ], - }); - }); -}); diff --git a/src/json-pack/json/__tests__/JsonEncoderDag.spec.ts b/src/json-pack/json/__tests__/JsonEncoderDag.spec.ts deleted file mode 100644 index 27a4c8bb58..0000000000 --- a/src/json-pack/json/__tests__/JsonEncoderDag.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {utf8} from '../../../util/buffers/strings'; -import {JsonEncoderDag} from '../JsonEncoderDag'; - -const writer = new Writer(16); -const encoder = new JsonEncoderDag(writer); - -describe('object', () => { - test('shorter and smaller keys are sorted earlier', () => { - const json = '{"aaaaaa":6,"aaaaab":7,"aaaaac":8,"aaaabb":9,"bbbbb":5,"cccc":4,"ddd":3,"ee":2,"f":1}'; - const data = JSON.parse(json); - const encoded = encoder.encode(data); - const json2 = Buffer.from(encoded).toString(); - expect(json2).toBe('{"f":1,"ee":2,"ddd":3,"cccc":4,"bbbbb":5,"aaaaaa":6,"aaaaab":7,"aaaaac":8,"aaaabb":9}'); - }); -}); - -describe('Bytes', () => { - test('can encode a simple buffer in object', () => { - const buf = utf8`hello world`; - const data = {foo: buf}; - const encoded = encoder.encode(data); - const json = Buffer.from(encoded).toString(); - expect(json).toBe('{"foo":{"/":{"bytes":"aGVsbG8gd29ybGQ"}}}'); - }); - - test('can encode a simple buffer in array', () => { - const buf = utf8`hello world`; - const data = [0, buf, 1]; - const encoded = encoder.encode(data); - const json = Buffer.from(encoded).toString(); - expect(json).toBe('[0,{"/":{"bytes":"aGVsbG8gd29ybGQ"}},1]'); - }); -}); - -describe('Cid', () => { - class CID { - constructor(public readonly value: string) {} - } - - class IpfsEncoder extends JsonEncoderDag { - public writeUnknown(value: unknown): void { - if (value instanceof CID) return this.writeCid(value.value); - else super.writeUnknown(value); - } - } - - const encoder = new IpfsEncoder(writer); - - test('can encode a CID as object key', () => { - const data = {id: new CID('QmXn5v3z')}; - const encoded = encoder.encode(data); - const json = Buffer.from(encoded).toString(); - expect(json).toBe('{"id":{"/":"QmXn5v3z"}}'); - }); - - test('can encode a CID in array', () => { - const data = ['a', new CID('b'), 'c']; - const encoded = encoder.encode(data); - const json = Buffer.from(encoded).toString(); - expect(json).toBe('["a",{"/":"b"},"c"]'); - }); -}); diff --git a/src/json-pack/json/__tests__/automated.spec.ts b/src/json-pack/json/__tests__/automated.spec.ts deleted file mode 100644 index 534c942243..0000000000 --- a/src/json-pack/json/__tests__/automated.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {JsonEncoder} from '../JsonEncoder'; -import {JsonEncoderStable} from '../JsonEncoderStable'; -import {JsonDecoder} from '../JsonDecoder'; -import {documents} from '../../../__tests__/json-documents'; -import {binaryDocuments} from '../../../__tests__/binary-documents'; - -const writer = new Writer(8); -const encoder = new JsonEncoder(writer); -const encoderStable = new JsonEncoderStable(writer); -const decoder = new JsonDecoder(); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - const encoded2 = encoderStable.encode(value); - // const json = Buffer.from(encoded).toString('utf-8'); - // console.log('json', json); - const decoded = decoder.decode(encoded); - const decoded2 = decoder.decode(encoded2); - expect(decoded).toEqual(value); - expect(decoded2).toEqual(value); -}; - -describe('Sample JSON documents', () => { - for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - assertEncoder(t.json as any); - }); - } -}); - -describe('Sample binary documents', () => { - for (const t of binaryDocuments) { - (t.only ? test.only : test)(t.name, () => { - assertEncoder(t.json as any); - }); - } -}); diff --git a/src/json-pack/json/__tests__/fuzzer.spec.ts b/src/json-pack/json/__tests__/fuzzer.spec.ts deleted file mode 100644 index e4b7661c0a..0000000000 --- a/src/json-pack/json/__tests__/fuzzer.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {RandomJson} from '../../../json-random'; -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {JsonDecoder} from '../JsonDecoder'; -import {JsonEncoder} from '../JsonEncoder'; - -const writer = new Writer(1); -const encoder = new JsonEncoder(writer); -const decoder = new JsonDecoder(); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - const json = Buffer.from(encoded).toString('utf-8'); - try { - decoder.reader.reset(encoded); - const decoded = decoder.readAny(); - // console.log('decoded', decoded); - expect(decoded).toEqual(value); - } catch (error) { - /* tslint:disable no-console */ - console.log('value', value); - console.log('JSON.stringify', JSON.stringify(value)); - console.log('JsonEncoder', json); - /* tslint:enable no-console */ - throw error; - } -}; - -test('fuzzing', () => { - for (let i = 0; i < 1000; i++) { - const json = RandomJson.generate(); - assertEncoder(json); - } -}, 50000); diff --git a/src/json-pack/json/__tests__/memory-leaks.spec.ts b/src/json-pack/json/__tests__/memory-leaks.spec.ts deleted file mode 100644 index 525cc350f9..0000000000 --- a/src/json-pack/json/__tests__/memory-leaks.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {JsonEncoder} from '../JsonEncoder'; -import {parse} from '../../../json-binary'; -import largeJson from '../../../__bench__/data/json-very-large-object'; - -const writer = new Writer(1024 * 64); -const encoder = new JsonEncoder(writer); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - const json = Buffer.from(encoded).toString('utf-8'); - // console.log('json', json); - const decoded = parse(json); - expect(decoded).toEqual(value); -}; - -describe('should keep writing buffer memory within limits', () => { - test('long string', () => { - for (let i = 0; i < 1000; i++) { - const value = { - foo: 'a'.repeat(Math.round(32000 * Math.random()) + 10), - }; - assertEncoder(value); - // console.log(writer.uint8.length); - expect(writer.uint8.length).toBeLessThan(1024 * 64 * 5 * 5); - } - }); - - test('large object', () => { - for (let i = 0; i < 100; i++) { - encoder.encode(largeJson); - // console.log(writer.uint8.length); - expect(writer.uint8.length).toBeLessThan(1024 * 64 * 5 * 5); - } - }); -}); diff --git a/src/json-pack/json/types.ts b/src/json-pack/json/types.ts deleted file mode 100644 index 109a72b60b..0000000000 --- a/src/json-pack/json/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type JsonUint8Array = Uint8Array & {__BRAND__: 'json'; __TYPE__: T}; diff --git a/src/json-pack/json/util.ts b/src/json-pack/json/util.ts deleted file mode 100644 index f708118e88..0000000000 --- a/src/json-pack/json/util.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const findEndingQuote = (uint8: Uint8Array, x: number): number => { - const len = uint8.length; - let char = uint8[x]; - let prev = 0; - while (x < len) { - if (char === 34 && prev !== 92) break; - if (char === 92 && prev === 92) prev = 0; - else prev = char; - char = uint8[++x]; - } - if (x === len) throw new Error('Invalid JSON'); - return x; -}; diff --git a/src/json-pack/msgpack/MsgPackDecoder.ts b/src/json-pack/msgpack/MsgPackDecoder.ts deleted file mode 100644 index 7da9929bed..0000000000 --- a/src/json-pack/msgpack/MsgPackDecoder.ts +++ /dev/null @@ -1,256 +0,0 @@ -import {JsonPackValue} from '.'; -import {MsgPackDecoderFast} from './MsgPackDecoderFast'; -import type {Path} from '../../json-pointer'; -import type {Reader} from '../../util/buffers/Reader'; - -/** - * @category Decoder - */ -export class MsgPackDecoder extends MsgPackDecoderFast { - // ---------------------------------------------------------- Skipping values - - /** - * Skips a whole JSON value and returns back the number of bytes - * that value consumed. - */ - public skipAny(): number { - const byte = this.reader.u8(); - if (byte >= 0xe0) return 1; // 0xe0 - if (byte <= 0xbf) { - if (byte < 0x90) { - if (byte <= 0b1111111) return 1; // 0x7f - return 1 + this.skipObj(byte & 0b1111); // 0x80, obj(1) - } else { - if (byte < 0xa0) return 1 + this.skipArr(byte & 0b1111); - // 0x90 - else return 1 + this.skip(byte & 0b11111); // 0xa0, str(1) - } - } - if (byte <= 0xd0) { - if (byte <= 0xc8) { - if (byte <= 0xc4) { - if (byte <= 0xc2) return byte === 0xc2 ? 1 : 1; - else return byte === 0xc4 ? 2 + this.skip(this.reader.u8()) : 1; - } else { - if (byte <= 0xc6) return byte === 0xc6 ? 5 + this.skip(this.reader.u32()) : 3 + this.skip(this.reader.u16()); - else return byte === 0xc8 ? 4 + this.skip(this.reader.u16()) : 3 + this.skip(this.reader.u8()); - } - } else { - return byte <= 0xcc - ? byte <= 0xca - ? byte === 0xca - ? 1 + this.skip(4) // f32 - : 1 + 1 + 4 + this.skip(this.reader.u32()) // ext32 - : byte === 0xcc - ? 1 + this.skip(1) // u8 - : 1 + this.skip(8) // f64 - : byte <= 0xce - ? byte === 0xce - ? 1 + this.skip(4) // u32 - : 1 + this.skip(2) // u16 - : byte === 0xd0 - ? 1 + this.skip(1) // i8 - : 1 + this.skip(8); // u64 - } - } else if (byte <= 0xd8) { - return byte <= 0xd4 - ? byte <= 0xd2 - ? byte === 0xd2 - ? 1 + this.skip(4) // i32 - : 1 + this.skip(2) // i16 - : byte === 0xd4 - ? 1 + this.skip(2) // ext1 - : 1 + this.skip(8) // i64 - : byte <= 0xd6 - ? byte === 0xd6 - ? 1 + this.skip(5) // ext4 - : 1 + this.skip(3) // ext2 - : byte === 0xd8 - ? 1 + this.skip(17) // ext16 - : 1 + this.skip(9); // ext8 - } else { - switch (byte) { - case 0xd9: - return 2 + this.skip(this.reader.u8()); // str8 - case 0xda: - return 3 + this.skip(this.reader.u16()); // str16 - case 0xdb: - return 5 + this.skip(this.reader.u32()); // str32 - case 0xdc: - return 3 + this.skipArr(this.reader.u16()); - case 0xdd: - return 5 + this.skipArr(this.reader.u32()); - case 0xde: - return 3 + this.skipObj(this.reader.u16()); - case 0xdf: - return 5 + this.skipObj(this.reader.u32()); - } - } - return 1; - } - - /** @ignore */ - protected skipArr(size: number): number { - let length = 0; - for (let i = 0; i < size; i++) length += this.skipAny(); - return length; - } - - /** @ignore */ - protected skipObj(size: number): number { - let length = 0; - for (let i = 0; i < size; i++) { - length += this.skipAny() + this.skipAny(); - } - return length; - } - - // -------------------------------------------------------- One level reading - - public readLevel(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.valOneLevel(); - } - - protected valOneLevel(): unknown { - const byte = this.reader.view.getUint8(this.reader.x); - const isMap = byte === 0xde || byte === 0xdf || byte >> 4 === 0b1000; - if (isMap) { - this.reader.x++; - const size = byte === 0xde ? this.reader.u16() : byte === 0xdf ? this.reader.u32() : byte & 0b1111; - const obj: Record = {}; - for (let i = 0; i < size; i++) { - const key = this.key(); - obj[key] = this.primitive(); - } - return obj; - } - const isArray = byte === 0xdc || byte === 0xdd || byte >> 4 === 0b1001; - if (isArray) { - this.reader.x++; - const size = byte === 0xdc ? this.reader.u16() : byte === 0xdd ? this.reader.u32() : byte & 0b1111; - const arr: unknown[] = []; - for (let i = 0; i < size; i++) arr.push(this.primitive()); - return arr; - } - return this.val(); - } - - /** - * @ignore - * @returns Returns a primitive value or {@link JsonPackValue} object, if the value - * is a "map" or an "arr". - */ - protected primitive(): unknown { - const reader = this.reader; - const byte = reader.view.getUint8(reader.x); - const isMapOrArray = byte === 0xde || byte === 0xdf || byte === 0xdc || byte === 0xdd || byte >> 5 === 0b100; - if (isMapOrArray) { - const length = this.skipAny(); - reader.x -= length; - const buf = reader.buf(length); - return new JsonPackValue(buf); - } - return this.val(); - } - - protected skip(length: number): number { - this.reader.x += length; - return length; - } - - // --------------------------------------------------------------- Validation - - /** - * Throws if at given offset in a buffer there is an invalid MessagePack - * value, or if the value does not span the exact length specified in `size`. - * I.e. throws if: - * - * - The value is not a valid MessagePack value. - * - The value is shorter than `size`. - * - The value is longer than `size`. - * - * @param value Buffer in which to validate MessagePack value. - * @param offset Offset at which the value starts. - * @param size Expected size of the value. - */ - public validate(value: Uint8Array, offset: number = 0, size: number = value.length): void { - this.reader.reset(value); - this.reader.x = offset; - const start = offset; - this.skipAny(); - const end = this.reader.x; - if (end - start !== size) throw new Error('INVALID_SIZE'); - } - - // ---------------------------------------------------------- Shallow reading - - public readObjHdr(): number { - const reader = this.reader; - const byte = reader.u8(); - const isFixMap = byte >> 4 === 0b1000; - if (isFixMap) return byte & 0b1111; - switch (byte) { - case 0xde: - return reader.u16(); - case 0xdf: - return reader.u32(); - } - throw new Error('NOT_OBJ'); - } - - public readStrHdr(): number { - const reader = this.reader; - const byte = reader.u8(); - if (byte >> 5 === 0b101) return byte & 0b11111; - switch (byte) { - case 0xd9: - return reader.u8(); - case 0xda: - return reader.u16(); - case 0xdb: - return reader.u32(); - } - throw new Error('NOT_STR'); - } - - public findKey(key: string): this { - const size = this.readObjHdr(); - for (let i = 0; i < size; i++) { - const k = this.key(); - if (k === key) return this; - this.skipAny(); - } - throw new Error('KEY_NOT_FOUND'); - } - - public readArrHdr(): number { - const reader = this.reader; - const byte = reader.u8(); - const isFixArr = byte >> 4 === 0b1001; - if (isFixArr) return byte & 0b1111; - switch (byte) { - case 0xdc: - return this.reader.u16(); - case 0xdd: - return this.reader.u32(); - } - throw new Error('NOT_ARR'); - } - - public findIndex(index: number): this { - const size = this.readArrHdr(); - if (index >= size) throw new Error('INDEX_OUT_OF_BOUNDS'); - for (let i = 0; i < index; i++) this.skipAny(); - return this; - } - - public find(path: Path): this { - for (let i = 0; i < path.length; i++) { - const segment = path[i]; - if (typeof segment === 'string') this.findKey(segment); - else this.findIndex(segment); - } - return this; - } -} diff --git a/src/json-pack/msgpack/MsgPackDecoderFast.ts b/src/json-pack/msgpack/MsgPackDecoderFast.ts deleted file mode 100644 index 140851da89..0000000000 --- a/src/json-pack/msgpack/MsgPackDecoderFast.ts +++ /dev/null @@ -1,181 +0,0 @@ -import {JsonPackExtension} from '../JsonPackExtension'; -import {Reader} from '../../util/buffers/Reader'; -import {ERROR} from '../cbor/constants'; -import sharedCachedUtf8Decoder from '../../util/buffers/utf8/sharedCachedUtf8Decoder'; -import type {BinaryJsonDecoder, PackValue} from '../types'; -import type {CachedUtf8Decoder} from '../../util/buffers/utf8/CachedUtf8Decoder'; - -/** - * @category Decoder - */ -export class MsgPackDecoderFast implements BinaryJsonDecoder { - public constructor( - public reader: R = new Reader() as R, - protected readonly keyDecoder: CachedUtf8Decoder = sharedCachedUtf8Decoder, - ) {} - - /** @deprecated */ - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.val(); - } - - public read(uint8: Uint8Array): PackValue { - this.reader.reset(uint8); - return this.val() as PackValue; - } - - public val(): unknown { - const reader = this.reader; - const byte = reader.u8(); - if (byte >= 0xe0) return byte - 0x100; // 0xe0 - if (byte <= 0xbf) { - if (byte < 0x90) { - if (byte <= 0b1111111) return byte; // 0x7f - return this.obj(byte & 0b1111); // 0x80 - } else { - if (byte < 0xa0) return this.arr(byte & 0b1111); - // 0x90 - else return reader.utf8(byte & 0b11111); // 0xa0 - } - } - if (byte <= 0xd0) { - if (byte <= 0xc8) { - if (byte <= 0xc4) { - if (byte <= 0xc2) return byte === 0xc2 ? false : byte === 0xc0 ? null : undefined; - else return byte === 0xc4 ? reader.buf(reader.u8()) : true; - } else { - if (byte <= 0xc6) return byte === 0xc6 ? reader.buf(reader.u32()) : reader.buf(reader.u16()); - else return byte === 0xc8 ? this.ext(reader.u16()) : this.ext(reader.u8()); - } - } else { - return byte <= 0xcc - ? byte <= 0xca - ? byte === 0xca - ? reader.f32() - : this.ext(reader.u32()) - : byte === 0xcc - ? reader.u8() - : reader.f64() - : byte <= 0xce - ? byte === 0xce - ? reader.u32() - : reader.u16() - : byte === 0xd0 - ? reader.i8() - : reader.u32() * 4294967296 + reader.u32(); - } - } else if (byte <= 0xd8) { - return byte <= 0xd4 - ? byte <= 0xd2 - ? byte === 0xd2 - ? reader.i32() - : reader.i16() - : byte === 0xd4 - ? this.ext(1) - : reader.i32() * 4294967296 + reader.u32() - : byte <= 0xd6 - ? byte === 0xd6 - ? this.ext(4) - : this.ext(2) - : byte === 0xd8 - ? this.ext(16) - : this.ext(8); - } else { - switch (byte) { - case 0xd9: - return reader.utf8(reader.u8()); - case 0xda: - return reader.utf8(reader.u16()); - case 0xdb: - return reader.utf8(reader.u32()); - case 0xdc: - return this.arr(reader.u16()); - case 0xdd: - return this.arr(reader.u32()); - case 0xde: - return this.obj(reader.u16()); - case 0xdf: - return this.obj(reader.u32()); - } - } - return undefined; - } - - public str(): unknown { - const reader = this.reader; - const byte = reader.u8(); - if (byte >> 5 === 0b101) return reader.utf8(byte & 0b11111); - switch (byte) { - case 0xd9: - return reader.utf8(reader.u8()); - case 0xda: - return reader.utf8(reader.u16()); - case 0xdb: - return reader.utf8(reader.u32()); - } - return undefined; - } - - /** @ignore */ - protected obj(size: number): object { - const obj: Record = {}; - for (let i = 0; i < size; i++) { - const key = this.key(); - if (key === '__proto__') throw ERROR.UNEXPECTED_OBJ_KEY; - obj[key] = this.val(); - } - return obj; - } - - /** @ignore */ - protected key(): string { - const reader = this.reader; - const byte = reader.view.getUint8(reader.x); - if (byte >= 0b10100000 && byte <= 0b10111111) { - const size = byte & 0b11111; - const key = this.keyDecoder.decode(reader.uint8, reader.x + 1, size); - reader.x += 1 + size; - return key; - } else if (byte === 0xd9) { - const size = reader.view.getUint8(reader.x + 1); - if (size < 32) { - const key = this.keyDecoder.decode(reader.uint8, reader.x + 2, size); - reader.x += 2 + size; - return key; - } - } - reader.x++; - switch (byte) { - case 0xd9: - return reader.utf8(reader.u8()); - case 0xda: - return reader.utf8(reader.u16()); - case 0xdb: - return reader.utf8(reader.u32()); - default: - return ''; - } - } - - /** @ignore */ - protected arr(size: number): unknown[] { - const arr: unknown[] = []; - for (let i = 0; i < size; i++) arr.push(this.val()); - return arr; - } - - /** @ignore */ - protected ext(size: number): JsonPackExtension { - const reader = this.reader; - const type = reader.u8(); - const end = reader.x + size; - const buf = reader.uint8.subarray(reader.x, end); - reader.x = end; - return new JsonPackExtension(type, buf); - } - - protected back(bytes: number) { - this.reader.x -= bytes; - } -} diff --git a/src/json-pack/msgpack/MsgPackEncoder.ts b/src/json-pack/msgpack/MsgPackEncoder.ts deleted file mode 100644 index 84320b529f..0000000000 --- a/src/json-pack/msgpack/MsgPackEncoder.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {MsgPackEncoderFast} from './MsgPackEncoderFast'; -import {isUint8Array} from '../../util/buffers/isUint8Array'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {JsonPackValue} from '../JsonPackValue'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import {MSGPACK} from './constants'; - -/** - * @category Encoder - */ -export class MsgPackEncoder< - W extends IWriter & IWriterGrowable = IWriter & IWriterGrowable, -> extends MsgPackEncoderFast { - public writeAny(value: unknown): void { - switch (value) { - case null: - return this.writer.u8(MSGPACK.NULL); - case false: - return this.writer.u8(MSGPACK.FALSE); - case true: - return this.writer.u8(MSGPACK.TRUE); - } - if (value instanceof Array) return this.encodeArray(value); - switch (typeof value) { - case 'number': - return this.encodeNumber(value); - case 'string': - return this.encodeString(value); - case 'object': { - if (value instanceof JsonPackValue) return this.writer.buf(value.val, value.val.length); - if (value instanceof JsonPackExtension) return this.encodeExt(value); - if (isUint8Array(value)) return this.encodeBinary(value); - return this.encodeObject(value as Record); - } - case 'undefined': - return this.writer.u8(MSGPACK.UNDEFINED); - } - } -} diff --git a/src/json-pack/msgpack/MsgPackEncoderFast.ts b/src/json-pack/msgpack/MsgPackEncoderFast.ts deleted file mode 100644 index 075e9f4798..0000000000 --- a/src/json-pack/msgpack/MsgPackEncoderFast.ts +++ /dev/null @@ -1,324 +0,0 @@ -import {IWriter, IWriterGrowable} from '../../util/buffers'; -import {Writer} from '../../util/buffers/Writer'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {BinaryJsonEncoder, TlvBinaryJsonEncoder} from '../types'; -import {IMessagePackEncoder} from './types'; - -/** - * @category Encoder - */ -export class MsgPackEncoderFast - implements IMessagePackEncoder, BinaryJsonEncoder, TlvBinaryJsonEncoder -{ - constructor(public readonly writer: W = new Writer() as any) {} - - /** - * Use this method to encode a JavaScript document into MessagePack format. - * - * @param json JSON value to encode. - * @returns Encoded memory buffer with MessagePack contents. - */ - public encode(json: unknown): Uint8Array { - this.writer.reset(); - this.writeAny(json); - return this.writer.flush(); - } - - /** @deprecated */ - public encodeAny(json: unknown): void { - this.writeAny(json); - } - - public writeAny(value: unknown): void { - switch (value) { - case null: - return this.writer.u8(0xc0); - case false: - return this.writer.u8(0xc2); - case true: - return this.writer.u8(0xc3); - } - if (value instanceof Array) return this.writeArr(value); - switch (typeof value) { - case 'number': - return this.writeNumber(value); - case 'string': - return this.writeStr(value); - case 'object': - return this.writeObj(value as Record); - } - } - - /** @deprecated */ - protected encodeFloat64(num: number): void { - this.writeFloat(num); - } - - public writeNull(): void { - return this.writer.u8(0xc0); - } - - public writeFloat(float: number): void { - this.writer.u8f64(0xcb, float); - } - - public u32(num: number): void { - const writer = this.writer; - this.writer.ensureCapacity(5); - const uint8 = writer.uint8; - if (num <= 0b1111111) { - uint8[writer.x++] = num; - // Commenting this out improves performance, there is not much space savings. - // } else if (num <= 0xff) { - // uint8[writer.x++] = 0xcc; - // uint8[writer.x++] = num; - } else if (num <= 0xffff) { - uint8[writer.x++] = 0xcd; - writer.view.setUint16(writer.x, num); - writer.x += 2; - } else if (num <= 0xffffffff) { - uint8[writer.x++] = 0xce; - writer.view.setUint32(writer.x, num); - writer.x += 4; - } else this.writeFloat(num); - } - - public n32(num: number): void { - const writer = this.writer; - this.writer.ensureCapacity(5); - const uint8 = writer.uint8; - if (num >= -0x20) { - uint8[writer.x++] = 0x100 + num; - // Commenting this out improves performance, there is not much space savings. - // } else if (num >= -0x80) { - // uint8[writer.x++] = 0xd0; - // uint8[writer.x++] = num + 0x100; - } else if (num >= -0x8000) { - uint8[writer.x++] = 0xd1; - writer.view.setInt16(writer.x, num); - writer.x += 2; - } else if (num >= -0x80000000) { - uint8[writer.x++] = 0xd2; - writer.view.setInt32(writer.x, num); - writer.x += 4; - } else this.writeFloat(num); - } - - /** @deprecated */ - public encodeNumber(num: number): void { - this.writeNumber(num); - } - - public writeNumber(num: number): void { - if (num >>> 0 === num) return this.u32(num); - if (num >> 0 === num) return this.n32(num); - this.writeFloat(num); - } - - public writeInteger(int: number): void { - if (int >= 0) - if (int <= 0xffffffff) return this.u32(int); - else if (int > -0x80000000) return this.n32(int); - this.writeFloat(int); - } - - public writeUInteger(uint: number): void { - if (uint <= 0xffffffff) return this.u32(uint); - this.writeFloat(uint); - } - - public encodeNull(): void { - this.writer.u8(0xc0); - } - - public encodeTrue(): void { - this.writer.u8(0xc3); - } - - public encodeFalse(): void { - this.writer.u8(0xc2); - } - - /** @deprecated */ - public encodeBoolean(bool: boolean): void { - this.writeBoolean(bool); - } - - public writeBoolean(bool: boolean): void { - if (bool) this.writer.u8(0xc3); - else this.writer.u8(0xc2); - } - - /** @deprecated */ - public encodeStringHeader(length: number): void { - this.writeStrHdr(length); - } - - public writeStrHdr(length: number): void { - if (length <= 0b11111) this.writer.u8(0b10100000 | length); - else if (length <= 0xff) this.writer.u16(0xd900 + length); - else if (length <= 0xffff) this.writer.u8u16(0xda, length); - else this.writer.u8u32(0xdb, length); - } - - /** @deprecated */ - public encodeString(str: string) { - this.writeStr(str); - } - - public writeStr(str: string): void { - const writer = this.writer; - const length = str.length; - const maxSize = length * 4; - writer.ensureCapacity(5 + maxSize); - const uint8 = writer.uint8; - let lengthOffset: number = writer.x; - if (maxSize <= 0b11111) writer.x++; - else if (maxSize <= 0xff) { - uint8[writer.x++] = 0xd9; - lengthOffset = writer.x; - writer.x++; - } else if (maxSize <= 0xffff) { - uint8[writer.x++] = 0xda; - lengthOffset = writer.x; - writer.x += 2; - } else { - uint8[writer.x++] = 0xdb; - lengthOffset = writer.x; - writer.x += 4; - } - const bytesWritten = this.writer.utf8(str); - if (maxSize <= 0b11111) uint8[lengthOffset] = 0b10100000 | bytesWritten; - else if (maxSize <= 0xff) uint8[lengthOffset] = bytesWritten; - else if (maxSize <= 0xffff) writer.view.setUint16(lengthOffset, bytesWritten); - else writer.view.setUint32(lengthOffset, bytesWritten); - } - - /** @deprecated */ - public encodeAsciiString(str: string) { - this.writeAsciiStr(str); - } - - public writeAsciiStr(str: string): void { - this.writeStrHdr(str.length); - this.writer.ascii(str); - } - - /** @deprecated */ - public encodeArrayHeader(length: number): void { - this.writeArrHdr(length); - } - - /** @deprecated */ - public encodeArray(arr: unknown[]): void { - this.writeArr(arr); - } - - public writeArrHdr(length: number): void { - if (length <= 0b1111) this.writer.u8(0b10010000 | length); - else if (length <= 0xffff) this.writer.u8u16(0xdc, length); - else if (length <= 0xffffffff) this.writer.u8u32(0xdd, length); - } - - public writeArr(arr: unknown[]): void { - const length = arr.length; - if (length <= 0b1111) this.writer.u8(0b10010000 | length); - else if (length <= 0xffff) this.writer.u8u16(0xdc, length); - else if (length <= 0xffffffff) this.writer.u8u32(0xdd, length); - // else return; - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - } - - /** @deprecated */ - public encodeObjectHeader(length: number): void { - this.writeObjHdr(length); - } - - /** @deprecated */ - public encodeObject(obj: Record): void { - this.writeObj(obj); - } - - public writeObjHdr(length: number): void { - if (length <= 0b1111) this.writer.u8(0b10000000 | length); - else if (length <= 0xffff) { - this.writer.u8u16(0xde, length); - } else if (length <= 0xffffffff) { - this.writer.u8u32(0xdf, length); - } - } - - public writeObj(obj: Record): void { - const keys = Object.keys(obj); - const length = keys.length; - this.writeObjHdr(length); - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } - - public encodeExtHeader(type: number, length: number) { - switch (length) { - case 1: - this.writer.u16((0xd4 << 8) | type); - break; - case 2: - this.writer.u16((0xd5 << 8) | type); - break; - case 4: - this.writer.u16((0xd6 << 8) | type); - break; - case 8: - this.writer.u16((0xd7 << 8) | type); - break; - case 16: - this.writer.u16((0xd8 << 8) | type); - break; - default: - if (length <= 0xff) { - this.writer.u16((0xc7 << 8) | length); - this.writer.u8(type); - } else if (length <= 0xffff) { - this.writer.u8u16(0xc8, length); - this.writer.u8(type); - } else if (length <= 0xffffffff) { - this.writer.u8u32(0xc9, length); - this.writer.u8(type); - } - } - } - - public encodeExt(ext: JsonPackExtension): void { - const {tag: type, val: buf} = ext; - const length = buf.length; - this.encodeExtHeader(type, length); - this.writer.buf(buf, length); - } - - /** @deprecated */ - public encodeBinaryHeader(length: number): void { - this.writeBinHdr(length); - } - - /** @deprecated */ - public encodeBinary(buf: Uint8Array): void { - this.writeBin(buf); - } - - public writeBinHdr(length: number): void { - if (length <= 0xff) this.writer.u16((0xc4 << 8) | length); - else if (length <= 0xffff) { - this.writer.u8u16(0xc5, length); - } else if (length <= 0xffffffff) { - this.writer.u8u32(0xc6, length); - } - } - - public writeBin(buf: Uint8Array): void { - const length = buf.length; - this.writeBinHdr(length); - this.writer.buf(buf, length); - } -} diff --git a/src/json-pack/msgpack/MsgPackEncoderStable.ts b/src/json-pack/msgpack/MsgPackEncoderStable.ts deleted file mode 100644 index 7b66a3051e..0000000000 --- a/src/json-pack/msgpack/MsgPackEncoderStable.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {sort} from '../../util/sort/insertion'; -import {MsgPackEncoderFast} from './MsgPackEncoderFast'; - -/** - * @category Encoder - */ -export class MsgPackEncoderStable extends MsgPackEncoderFast { - public writeObj(obj: Record): void { - const keys = sort(Object.keys(obj)); - const length = keys.length; - this.writeObjHdr(length); - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } -} diff --git a/src/json-pack/msgpack/MsgPackToJsonConverter.ts b/src/json-pack/msgpack/MsgPackToJsonConverter.ts deleted file mode 100644 index fa60d6edc3..0000000000 --- a/src/json-pack/msgpack/MsgPackToJsonConverter.ts +++ /dev/null @@ -1,241 +0,0 @@ -import {json_string} from '../../json-brand'; -import {asString} from '../../util/strings/asString'; -import {toDataUri} from '../../util/buffers/toDataUri'; - -/** - * @category Decoder - */ -export class MsgPackToJsonConverter { - /** @ignore */ - protected uint8 = new Uint8Array([]); - /** @ignore */ - protected view = new DataView(this.uint8.buffer); - /** @ignore */ - protected x = 0; - - public constructor() {} - - public reset(uint8: Uint8Array): void { - this.x = 0; - this.uint8 = uint8; - this.view = new DataView(uint8.buffer, uint8.byteOffset, uint8.length); - } - - /** - * Converts a MessagePack blob directly to JSON string. - * - * @param uint8 Binary data with MessagePack encoded value. - * @returns JSON string. - */ - public convert(uint8: Uint8Array): json_string { - this.reset(uint8); - return this.val() as json_string; - } - - /** @ignore */ - protected val(): string { - const byte = this.u8(); - if (byte >= 0xe0) return (byte - 0x100).toString(); // 0xe0 - if (byte <= 0xbf) { - if (byte < 0x90) { - if (byte <= 0b1111111) return byte.toString(); // 0x7f - return this.obj(byte & 0b1111); // 0x80 - } else { - if (byte < 0xa0) return this.arr(byte & 0b1111); - // 0x90 - else return this.str(byte & 0b11111); // 0xa0 - } - } - if (byte <= 0xd0) { - if (byte <= 0xc8) { - if (byte <= 0xc4) { - if (byte <= 0xc2) return byte === 0xc2 ? 'false' : 'null'; - else return byte === 0xc4 ? this.bin(this.u8()) : 'true'; - } else { - if (byte <= 0xc6) return byte === 0xc6 ? this.bin(this.u32()) : this.bin(this.u16()); - else return byte === 0xc8 ? this.ext(this.u16()) : this.ext(this.u8()); - } - } else { - return byte <= 0xcc - ? byte <= 0xca - ? byte === 0xca - ? this.f32().toString() - : this.ext(this.u32()) - : byte === 0xcc - ? this.u8().toString() - : this.f64().toString() - : byte <= 0xce - ? byte === 0xce - ? this.u32().toString() - : this.u16().toString() - : byte === 0xd0 - ? this.i8().toString() - : (this.u32() * 4294967296 + this.u32()).toString(); - } - } else if (byte <= 0xd8) { - return byte <= 0xd4 - ? byte <= 0xd2 - ? byte === 0xd2 - ? this.i32().toString() - : this.i16().toString() - : byte === 0xd4 - ? this.ext(1) - : (this.i32() * 4294967296 + this.i32()).toString() - : byte <= 0xd6 - ? byte === 0xd6 - ? this.ext(4) - : this.ext(2) - : byte === 0xd8 - ? this.ext(16) - : this.ext(8); - } else { - switch (byte) { - case 0xd9: - return this.str(this.u8()); - case 0xda: - return this.str(this.u16()); - case 0xdb: - return this.str(this.u32()); - case 0xdc: - return this.arr(this.u16()); - case 0xdd: - return this.arr(this.u32()); - case 0xde: - return this.obj(this.u16()); - case 0xdf: - return this.obj(this.u32()); - } - } - return ''; - } - - /** @ignore */ - protected str(size: number): string { - const uint8 = this.uint8; - const end = this.x + size; - let x = this.x; - let str = ''; - while (x < end) { - const b1 = uint8[x++]!; - if ((b1 & 0x80) === 0) { - str += String.fromCharCode(b1); - continue; - } else if ((b1 & 0xe0) === 0xc0) { - str += String.fromCharCode(((b1 & 0x1f) << 6) | (uint8[x++]! & 0x3f)); - } else if ((b1 & 0xf0) === 0xe0) { - str += String.fromCharCode(((b1 & 0x1f) << 12) | ((uint8[x++]! & 0x3f) << 6) | (uint8[x++]! & 0x3f)); - } else if ((b1 & 0xf8) === 0xf0) { - const b2 = uint8[x++]! & 0x3f; - const b3 = uint8[x++]! & 0x3f; - const b4 = uint8[x++]! & 0x3f; - let code = ((b1 & 0x07) << 0x12) | (b2 << 0x0c) | (b3 << 0x06) | b4; - if (code > 0xffff) { - code -= 0x10000; - str += String.fromCharCode(((code >>> 10) & 0x3ff) | 0xd800); - code = 0xdc00 | (code & 0x3ff); - } - str += String.fromCharCode(code); - } else { - str += String.fromCharCode(b1); - } - } - this.x = end; - return asString(str); - } - - /** @ignore */ - protected obj(size: number): json_string { - let str = '{'; - for (let i = 0; i < size; i++) { - if (i > 0) str += ','; - str += this.key(); - str += ':'; - str += this.val(); - } - return (str + '}') as json_string; - } - - /** @ignore */ - protected key(): json_string { - return this.val() as json_string; - } - - /** @ignore */ - protected arr(size: number): json_string { - let str = '['; - for (let i = 0; i < size; i++) { - if (i > 0) str += ','; - str += this.val(); - } - return (str + ']') as json_string; - } - - /** @ignore */ - protected bin(size: number): string { - const end = this.x + size; - const buf = this.uint8.subarray(this.x, end); - this.x = end; - return '"' + toDataUri(buf) + '"'; - } - - /** @ignore */ - protected ext(size: number): string { - const ext = this.u8(); - const end = this.x + size; - const buf = this.uint8.subarray(this.x, end); - this.x = end; - return '"' + toDataUri(buf, {ext}) + '"'; - } - - /** @ignore */ - protected u8(): number { - return this.view.getUint8(this.x++); - } - - /** @ignore */ - protected u16(): number { - const num = this.view.getUint16(this.x); - this.x += 2; - return num; - } - - /** @ignore */ - protected u32(): number { - const num = this.view.getUint32(this.x); - this.x += 4; - return num; - } - - /** @ignore */ - protected i8(): number { - return this.view.getInt8(this.x++); - } - - /** @ignore */ - protected i16(): number { - const num = this.view.getInt16(this.x); - this.x += 2; - return num; - } - - /** @ignore */ - protected i32(): number { - const num = this.view.getInt32(this.x); - this.x += 4; - return num; - } - - /** @ignore */ - protected f32(): number { - const pos = this.x; - this.x += 4; - return this.view.getFloat32(pos); - } - - /** @ignore */ - protected f64(): number { - const pos = this.x; - this.x += 8; - return this.view.getFloat64(pos); - } -} diff --git a/src/json-pack/msgpack/README.md b/src/json-pack/msgpack/README.md deleted file mode 100644 index 6845052622..0000000000 --- a/src/json-pack/msgpack/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# `json-pack` MessagePack Codec - -Fast and lean implementation of [MessagePack](https://github.com/msgpack/msgpack/blob/master/spec.md) codec. - -- Fastest implementation of MessagePack in JavaScript. -- Small footprint, small bundle size. -- Works in Node.js and browser. -- Supports binary fields. -- Supports extensions. -- Supports precomputed MessagePack values. - - -## Benchmarks - -Faster than built-in `JSON.stringify` and `JSON.parse`, and any other library. - -Encoding a 854 byte JSON object: - -``` -node benchmarks/json-pack.js -Size: 854 -json-joy/json-pack (v4) x 372,149 ops/sec ±0.63% (96 runs sampled), 2687 ns/op -json-joy/json-pack (v3) x 273,234 ops/sec ±0.74% (95 runs sampled), 3660 ns/op -json-joy/json-pack (v2) x 329,977 ops/sec ±0.48% (95 runs sampled), 3031 ns/op -JSON.stringify x 303,455 ops/sec ±0.94% (97 runs sampled), 3295 ns/op -@msgpack/msgpack x 211,446 ops/sec ±0.75% (90 runs sampled), 4729 ns/op -msgpack-lite x 106,048 ops/sec ±2.80% (90 runs sampled), 9430 ns/op -msgpack5 x 18,336 ops/sec ±2.52% (84 runs sampled), 54537 ns/op -messagepack x 18,907 ops/sec ±3.36% (81 runs sampled), 52890 ns/op -Fastest is json-joy/json-pack (v4) -``` - -Decoding a 584 byte JSON object: - -``` -node benchmarks/json-pack.Decoder.js -json-joy/json-pack x 258,215 ops/sec ±0.97% (90 runs sampled), 3873 ns/op -JSON.parse x 224,616 ops/sec ±0.72% (91 runs sampled), 4452 ns/op -@msgpack/msgpack x 196,799 ops/sec ±0.74% (93 runs sampled), 5081 ns/op -msgpack x 62,323 ops/sec ±0.74% (92 runs sampled), 16045 ns/op -msgpack-lite x 52,794 ops/sec ±0.75% (92 runs sampled), 18941 ns/op -msgpack5 x 30,240 ops/sec ±0.76% (93 runs sampled), 33069 ns/op -messagepack x 2,740 ops/sec ±10.15% (49 runs sampled), 364983 ns/op -``` - - -## Usage - -### Basic usage - -Use `Encoder` to encode plain JSON values. - -```ts -import {Encoder, Decoder} from 'json-joy/{lib,es6,esm}/json-pack'; - -const encoder = new Encoder(); -const decoder = new Decoder(); -const buffer = encoder.encode({foo: 'bar'}); -const obj = decoder.decode(buffer); - -console.log(obj); // { foo: 'bar' } -``` - -Use `EncoderFull` to encode data that is more complex than plain JSON. For -example, encode binary data using `ArrayBuffer`: - -```ts -import {EncoderFull, Decoder} from 'json-joy/{lib,es6,esm}/json-pack'; - -const encoder = new EncoderFull(); -const decoder = new Decoder(); -const buffer = encoder.encode({foo: new Uint8Array([1, 2, 3]).buffer}); -const obj = decoder.decode(buffer); -console.log(obj); // { foo: ArrayBuffer { [1, 2, 3] } } -``` - - -### Pre-computed values - -You might have already encoded MessagePack value, to insert it into a bigger -MessagePack object as-is use `JsonPackValue` wrapper. - -```ts -import {EncoderFull, Decoder, JsonPackValue} from 'json-joy/{lib,es6,esm}/json-pack'; - -const encoder = new EncoderFull(); -const decoder = new Decoder(); -const buffer = encoder.encode({foo: 'bar'}); -const value = new JsonPackValue(buffer); -const buffer2 = encode({baz: value}); - -const obj = decoder.decode(buffer2); -console.log(obj); // { baz: { foo: 'bar' } } -``` - -### Extensions - -Use `JsonPackExtension` wrapper to encode extensions. - -```ts -import {EncoderFull, Decoder, JsonPackExtension} from 'json-joy/{lib,es6,esm}/json-pack'; - -const ext = new JsonPackExtension(1, new Uint8Array(8)); -const encoder = new EncoderFull(); -const decoder = new Decoder(); -const buffer = encoder.encode({foo: ext}); - -const obj = decoder.decode(buffe2); -console.log(obj); // { foo: JsonPackExtension } -``` - -### Decoding one level at a time - -You can use `.decodeOneLevel()` method to decode one level of objects or arrays -of Message Pack values at a time. Only the primitive values of the first level -are returned decoded, complex values—like objects and arrays—are -returned as `JsonPackValue` blobs. - -```ts -const msgPack = encoder.encode({ - a: 1, - b: [1], -}); -const decoded = decoder.decodeOneLevel(msgPack); -console.log(decoded); // { a: 1, b: JsonPackValue {} } -``` - -### Stable binary output - -Objects key order in JavaScript is not predictable, hence the same object can -result in different MessagePack blobs. Use `EncoderStable` to get stable -MessagePack blobs. - -```ts -import {EncoderStable} from 'json-joy/{lib,es6,esm}/json-pack'; - -const encoder = new EncoderStable(); - -const buf1 = encoder.encode({a: 1, b: 2}); -const buf2 = encoder.encode({b: 2, a: 1}); - -// buf1.equals(buf2) == true -``` diff --git a/src/json-pack/msgpack/__tests__/MsgPackDecoder.one-level.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackDecoder.one-level.spec.ts deleted file mode 100644 index 9a938c254b..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackDecoder.one-level.spec.ts +++ /dev/null @@ -1,311 +0,0 @@ -import {MsgPackDecoder} from '../MsgPackDecoder'; -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {JsonPackValue} from '../../JsonPackValue'; - -const encoder = new MsgPackEncoder(); -const decoder = new MsgPackDecoder(); -const encode = (x: unknown) => encoder.encode(x); -const decode = (x: Uint8Array, offset: number) => decoder.readLevel(x); - -describe('null', () => { - test('can decode null', () => { - const buf = encode(null); - const res = decode(buf, 0); - expect(res).toBe(null); - }); -}); - -describe('boolean', () => { - test('can decode false', () => { - const buf = encode(false); - const res = decode(buf, 0); - expect(res).toBe(false); - }); - - test('can decode true', () => { - const buf = encode(true); - const res = decode(buf, 0); - expect(res).toBe(true); - }); -}); - -describe('number', () => { - test('can decode positive fixint', () => { - const buf = new Uint8Array([123]); - const res = decode(buf, 0); - expect(res).toBe(123); - }); - - test('can decode positive fixint encoded at offset', () => { - const buf1 = new Uint8Array([0, 123]); - const buf2 = buf1.subarray(1); - const res = decode(buf2, 0); - expect(res).toBe(123); - }); - - test('can decode 0', () => { - const buf = encode(0); - const res = decode(buf, 0); - expect(res).toBe(0); - }); - - test('can decode negative fixint', () => { - const buf = encode(-1); - const res = decode(buf, 0); - expect(res).toBe(-1); - }); - - test('can decode negative fixint - 2', () => { - const buf = encode(-32); - const res = decode(buf, 0); - expect(res).toBe(-32); - }); - - test('can decode double', () => { - const buf = encode(3456.12345678902234); - const res = decode(buf, 0); - expect(res).toBe(3456.12345678902234); - }); - - test('can decode 8 byte negative int', () => { - const buf = encode(-4807526976); - const res = decode(buf, 0); - expect(res).toBe(-4807526976); - }); -}); - -describe('string', () => { - test('can decode empty string', () => { - const buf = encode(''); - const res = decode(buf, 0); - expect(res).toBe(''); - }); - - test('can decode short string', () => { - const buf = encode('abc'); - const res = decode(buf, 0); - expect(res).toBe('abc'); - }); - - test('can decode 31 char string', () => { - const buf = encode('1234567890123456789012345678901'); - const res = decode(buf, 0); - expect(res).toBe('1234567890123456789012345678901'); - }); - - test('can decode 32 char string', () => { - const buf = encode('12345678901234567890123456789012'); - const res = decode(buf, 0); - expect(res).toBe('12345678901234567890123456789012'); - }); - - test('can decode 255 char string', () => { - const str = 'a'.repeat(255); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode 256 char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode a long string', () => { - const arr = [218, 4, 192]; - for (let i = 0; i < 1216; i++) arr.push(101); - const uint8 = new Uint8Array(arr); - const res = decode(uint8, 0); - expect(res).toBe( - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', - ); - }); - - test('can decode 0xFFFF char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode 0xFFFF + 1 char string', () => { - const str = 'a'.repeat(0xffff + 1); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); -}); - -describe('array', () => { - test('can decode empty array', () => { - const buf = encode([]); - const res = decode(buf, 0); - expect(res).toEqual([]); - }); - - test('can decode one element array', () => { - const buf = encode(['abc']); - const res = decode(buf, 0); - expect(res).toEqual(['abc']); - }); - - test('can decode 15 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - const res = decode(buf, 0); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - }); - - test('can decode 16 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - const res = decode(buf, 0); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - }); - - test('can decode 255 element array', () => { - const arr = '3'.repeat(256).split('').map(Number); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF element array', () => { - const arr = '3'.repeat(0xffff).split('').map(Number); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF + 1 element array', () => { - const arr = '3'.repeat(0xffff + 1).split(''); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode nested array', () => { - const arr = [1, [2], 3]; - const buf = encode(arr); - const res = decode(buf, 0) as number[]; - expect(res[0]).toBe(1); - expect(res[1]).toStrictEqual(new JsonPackValue(encode([2]))); - expect(res[2]).toBe(3); - const arr2 = decoder.decode(encode(res)); - expect(arr2).toStrictEqual(arr); - }); - - test('can decode nested array - 2', () => { - const arr = [1, [2], [3, 4, [5]]]; - const buf = encode(arr); - const res = decode(buf, 0) as number[]; - expect(res[0]).toBe(1); - expect(res[1]).toStrictEqual(new JsonPackValue(encode([2]))); - expect(res[2]).toStrictEqual(new JsonPackValue(encode([3, 4, [5]]))); - const arr2 = decoder.decode(encode(res)); - expect(arr2).toStrictEqual(arr); - }); -}); - -describe('object', () => { - test('can decode empty object', () => { - const obj = {}; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode simple object', () => { - const obj = {foo: 'bar'}; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 14 key object', () => { - const obj: any = {}; - for (let i = 0; i < 15; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 15 key object', () => { - const obj: any = {}; - for (let i = 0; i < 15; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 16 key object', () => { - const obj: any = {}; - for (let i = 0; i < 16; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 32 key object', () => { - const obj: any = {}; - for (let i = 0; i < 32; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 255 key object', () => { - const obj: any = {}; - for (let i = 0; i < 255; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 256 key object', () => { - const obj: any = {}; - for (let i = 0; i < 256; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF + 1 key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff + 1; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode nested objects', () => { - const obj: any = { - a: {}, - b: [{}, {g: 123}], - c: 1, - d: 'asdf', - e: null, - f: false, - }; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toStrictEqual({ - c: 1, - d: 'asdf', - e: null, - f: false, - a: new JsonPackValue(encode({})), - b: new JsonPackValue(encode([{}, {g: 123}])), - }); - const obj2 = decoder.decode(encode(res)); - expect(obj2).toStrictEqual(obj); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackDecoder.shallow-reading.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackDecoder.shallow-reading.spec.ts deleted file mode 100644 index 69b3974418..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackDecoder.shallow-reading.spec.ts +++ /dev/null @@ -1,172 +0,0 @@ -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {MsgPackDecoder} from '../MsgPackDecoder'; - -const encoder = new MsgPackEncoder(); -const decoder = new MsgPackDecoder(); - -describe('shallow reading values, without parsing the document', () => { - describe('reading object header', () => { - test('can read object size of empty oject', () => { - const encoded = encoder.encode({}); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(0); - }); - - test('can read small object size', () => { - const encoded = encoder.encode({foo: 'bar', a: 1, b: 2}); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(3); - }); - - test('medium size object size', () => { - const encoded = encoder.encode({ - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - }); - decoder.reader.reset(encoded); - const size = decoder.readObjHdr(); - expect(size).toBe(17); - }); - - test('throws if value is not an object', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - expect(() => decoder.readObjHdr()).toThrowError(); - }); - }); - - describe('object key finding', () => { - test('can find object key', () => { - const encoded = encoder.encode({foo: 'bar'}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('foo').val(); - expect(decoded).toBe('bar'); - }); - - test('can find object key in the middle of the object', () => { - const encoded = encoder.encode({x: 123, y: 0, z: -1}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('y').val(); - expect(decoded).toBe(0); - }); - - test('can find object key at the end of the object', () => { - const encoded = encoder.encode({x: 123, y: 0, z: -1}); - decoder.reader.reset(encoded); - const decoded = decoder.findKey('z').val(); - expect(decoded).toBe(-1); - }); - }); - - describe('reading array header', () => { - test('can read array size of an empty array', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(0); - }); - - test('can read small array size', () => { - const encoded = encoder.encode(['bar', 1, 2]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(3); - }); - - test('medium size array size', () => { - const encoded = encoder.encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]); - decoder.reader.reset(encoded); - const size = decoder.readArrHdr(); - expect(size).toBe(17); - }); - - test('throws if value is not an array', () => { - const encoded = encoder.encode({}); - decoder.reader.reset(encoded); - expect(() => decoder.readArrHdr()).toThrowError(); - }); - }); - - describe('array index finding', () => { - test('can find value at beginning of array', () => { - const encoded = encoder.encode(['foobar']); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(0).val(); - expect(decoded).toBe('foobar'); - }); - - test('can find value in the middle of array', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(1).val(); - expect(decoded).toBe(2); - }); - - test('can find value at the end of array', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - const decoded = decoder.findIndex(2).val(); - expect(decoded).toBe(3); - }); - - test('throws if array index is out of bounds', () => { - const encoded = encoder.encode([1, 2, 3]); - decoder.reader.reset(encoded); - expect(() => decoder.findIndex(3).val()).toThrowError(); - }); - - test('throws when reading value from an empty array', () => { - const encoded = encoder.encode([]); - decoder.reader.reset(encoded); - expect(() => decoder.findIndex(0).val()).toThrowError(); - }); - }); - - test('can shallow read a deeply nested value', () => { - const encoded = encoder.encode({ - a: { - b: { - c: { - d: { - e: [1, 2, 3], - }, - hmm: [ - { - foo: 'bar', - }, - ], - }, - }, - }, - }); - - decoder.reader.reset(encoded); - const decoded1 = decoder.findKey('a').findKey('b').findKey('c').findKey('d').findKey('e').val(); - expect(decoded1).toStrictEqual([1, 2, 3]); - - decoder.reader.reset(encoded); - const decoded2 = decoder.findKey('a').findKey('b').findKey('c').findKey('d').findKey('e').findIndex(1).val(); - expect(decoded2).toBe(2); - - decoder.reader.reset(encoded); - const decoded3 = decoder.findKey('a').findKey('b').findKey('c').findKey('hmm').findIndex(0).findKey('foo').val(); - expect(decoded3).toBe('bar'); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackDecoder.validate.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackDecoder.validate.spec.ts deleted file mode 100644 index 271a3228cb..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackDecoder.validate.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {MsgPackDecoder} from '../MsgPackDecoder'; - -const encoder = new MsgPackEncoder(); -const decoder = new MsgPackDecoder(); - -test('value is too short, buffer too long', () => { - const encoded = encoder.encode(1.1); - decoder.validate(encoded); - const corrupted = new Uint8Array(encoded.length + 1); - corrupted.set(encoded); - expect(() => decoder.validate(corrupted)).toThrow(); -}); - -test('value is truncated, buffer too short', () => { - const encoded = encoder.encode(1.1); - decoder.validate(encoded); - const corrupted = encoded.subarray(0, encoded.length - 1); - expect(() => decoder.validate(corrupted)).toThrow(); -}); - -test('invalid value', () => { - const encoded = new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); - expect(() => decoder.validate(encoded)).toThrow(); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackDecoderFast.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackDecoderFast.spec.ts deleted file mode 100644 index 0836acbafe..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackDecoderFast.spec.ts +++ /dev/null @@ -1,301 +0,0 @@ -import {NullObject} from '../../../util/NullObject'; -import {MsgPackDecoderFast} from '../MsgPackDecoderFast'; -import {MsgPackEncoderFast} from '../MsgPackEncoderFast'; - -const encoder = new MsgPackEncoderFast(); -const decoder = new MsgPackDecoderFast(); -const encode = (x: unknown) => encoder.encode(x); -const decode = (x: Uint8Array, offset: number) => decoder.decode(x); - -describe('null', () => { - test('can decode null', () => { - const buf = encode(null); - const res = decode(buf, 0); - expect(res).toBe(null); - }); -}); - -describe('boolean', () => { - test('can decode false', () => { - const buf = encode(false); - const res = decode(buf, 0); - expect(res).toBe(false); - }); - - test('can decode true', () => { - const buf = encode(true); - const res = decode(buf, 0); - expect(res).toBe(true); - }); -}); - -describe('number', () => { - test('can decode positive fixint', () => { - const buf = new Uint8Array([123]); - const res = decode(buf, 0); - expect(res).toBe(123); - }); - - test('can decode positive fixint encoded at offset', () => { - const buf1 = new Uint8Array([0, 123]); - const buf2 = buf1.subarray(1); - const res = decode(buf2, 0); - expect(res).toBe(123); - }); - - test('can decode 0', () => { - const buf = encode(0); - const res = decode(buf, 0); - expect(res).toBe(0); - }); - - test('can decode negative fixint', () => { - const buf = encode(-1); - const res = decode(buf, 0); - expect(res).toBe(-1); - }); - - test('can decode negative fixint - 2', () => { - const buf = encode(-32); - const res = decode(buf, 0); - expect(res).toBe(-32); - }); - - test('can decode double', () => { - const buf = encode(3456.12345678902234); - const res = decode(buf, 0); - expect(res).toBe(3456.12345678902234); - }); - - test('can decode 8 byte negative int', () => { - const buf = encode(-4807526976); - const res = decode(buf, 0); - expect(res).toBe(-4807526976); - }); -}); - -describe('string', () => { - test('can decode empty string', () => { - const buf = encode(''); - const res = decode(buf, 0); - expect(res).toBe(''); - }); - - test('can decode short string', () => { - const buf = encode('abc'); - const res = decode(buf, 0); - expect(res).toBe('abc'); - }); - - test('can decode 31 char string', () => { - const buf = encode('1234567890123456789012345678901'); - const res = decode(buf, 0); - expect(res).toBe('1234567890123456789012345678901'); - }); - - test('can decode 32 char string', () => { - const buf = encode('12345678901234567890123456789012'); - const res = decode(buf, 0); - expect(res).toBe('12345678901234567890123456789012'); - }); - - test('can decode 255 char string', () => { - const str = 'a'.repeat(255); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode 256 char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode a long string', () => { - const arr = [218, 4, 192]; - for (let i = 0; i < 1216; i++) arr.push(101); - const uint8 = new Uint8Array(arr); - const res = decode(uint8, 0); - expect(res).toBe( - 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', - ); - }); - - test('can decode 0xFFFF char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); - - test('can decode 0xFFFF + 1 char string', () => { - const str = 'a'.repeat(0xffff + 1); - const buf = encode(str); - const res = decode(buf, 0); - expect(res).toBe(str); - }); -}); - -describe('array', () => { - test('can decode empty array', () => { - const buf = encode([]); - const res = decode(buf, 0); - expect(res).toEqual([]); - }); - - test('can decode one element array', () => { - const buf = encode(['abc']); - const res = decode(buf, 0); - expect(res).toEqual(['abc']); - }); - - test('can decode 15 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - const res = decode(buf, 0); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - }); - - test('can decode 16 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - const res = decode(buf, 0); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - }); - - test('can decode 255 element array', () => { - const arr = '3'.repeat(256).split('').map(Number); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF element array', () => { - const arr = '3'.repeat(0xffff).split('').map(Number); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF + 1 element array', () => { - const arr = '3'.repeat(0xffff + 1).split(''); - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode nested array', () => { - const arr = [1, [2], 3]; - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); - - test('can decode nested array - 2', () => { - const arr = [1, [2], [3, 4, [5]]]; - const buf = encode(arr); - const res = decode(buf, 0); - expect(res).toEqual(arr); - }); -}); - -describe('object', () => { - test('can decode empty object', () => { - const obj = {}; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode simple object', () => { - const obj = {foo: 'bar'}; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 14 key object', () => { - const obj: any = {}; - for (let i = 0; i < 15; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 15 key object', () => { - const obj: any = {}; - for (let i = 0; i < 15; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 16 key object', () => { - const obj: any = {}; - for (let i = 0; i < 16; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 32 key object', () => { - const obj: any = {}; - for (let i = 0; i < 32; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 255 key object', () => { - const obj: any = {}; - for (let i = 0; i < 255; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 256 key object', () => { - const obj: any = {}; - for (let i = 0; i < 256; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF + 1 key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff + 1; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('can decode nested objects', () => { - const obj: any = { - a: {}, - b: { - c: {}, - d: {g: 123}, - }, - }; - const buf = encode(obj); - const res = decode(buf, 0); - expect(res).toEqual(obj); - }); - - test('throws on __proto__ key', () => { - const obj = new NullObject(); - // tslint:disable-next-line: no-string-literal - obj['__proto__'] = 123; - const buf = encode(obj); - expect(() => decode(buf, 0)).toThrow(); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackEncoder.codec.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackEncoder.codec.spec.ts deleted file mode 100644 index 649b6ef876..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackEncoder.codec.spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {JsonPackExtension} from '../../JsonPackExtension'; -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {MsgPackDecoderFast} from '..'; -import {documents} from '../../../__tests__/json-documents'; - -const encoder = new MsgPackEncoder(); -const encode = (x: unknown) => encoder.encode(x); -const decoder = new MsgPackDecoderFast(); -const decode = (a: Uint8Array) => decoder.decode(a); - -const tests: Array<{name: string; json: unknown}> = [ - ...documents, - { - name: 'simple ArrayBuffer', - json: new Uint8Array([1, 2, 3]), - }, - { - name: 'empty ArrayBuffer', - json: new Uint8Array([]), - }, - { - name: '255 byte ArrayBuffer', - json: new Uint8Array(255), - }, - { - name: '256 byte ArrayBuffer', - json: new Uint8Array(256), - }, - { - name: '0xFFFF byte ArrayBuffer', - json: new Uint8Array(0xffff), - }, - { - name: '0xFFFF + 1 byte ArrayBuffer', - json: new Uint8Array(0xffff + 1), - }, - { - name: '1 byte extension', - json: new JsonPackExtension(1, new Uint8Array([1])), - }, - { - name: '2 byte extension', - json: new JsonPackExtension(1, new Uint8Array([1, 1])), - }, - { - name: '4 byte extension', - json: new JsonPackExtension(6, new Uint8Array([1, 1, 2, 5])), - }, - { - name: '8 byte extension', - json: new JsonPackExtension(213, new Uint8Array([1, 1, 2, 5, 0, 0, 3, 3])), - }, - { - name: '16 byte extension', - json: new JsonPackExtension(0, new Uint8Array([1, 1, 2, 5, 0, 0, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2])), - }, - { - name: '10 byte extension', - json: new JsonPackExtension(10, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])), - }, - { - name: '255 byte extension', - json: new JsonPackExtension(10, new Uint8Array(255)), - }, - { - name: '256 byte extension', - json: new JsonPackExtension(11, new Uint8Array(256)), - }, - { - name: '0xFFFF byte extension', - json: new JsonPackExtension(12, new Uint8Array(0xffff)), - }, - { - name: '0xFFFF + 1 byte extension', - json: new JsonPackExtension(12, new Uint8Array(0xffff + 1)), - }, - { - name: '0xFFFFF byte extension', - json: new JsonPackExtension(12, new Uint8Array(0xfffff)), - }, -]; - -for (const t of tests) { - test(t.name, () => { - const buf = encode(t.json); - const res = decode(buf); - expect(res).toEqual(t.json); - }); -} diff --git a/src/json-pack/msgpack/__tests__/MsgPackEncoder.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackEncoder.spec.ts deleted file mode 100644 index f6beda07c7..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackEncoder.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {JsonPackExtension} from '../../JsonPackExtension'; -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {MsgPackDecoderFast} from '..'; -import {JsonPackValue} from '../../JsonPackValue'; - -const encoder = new MsgPackEncoder(); -const encode = (x: unknown) => encoder.encode(x); -const decoder = new MsgPackDecoderFast(); -const decode = (a: Uint8Array) => decoder.decode(a); - -describe('binary', () => { - test('can encode a simple Uin8Array', () => { - const data = {foo: new Uint8Array([3, 2, 1])}; - const arr = encode(data); - const res = decode(arr); - expect(res).toEqual(data); - expect((res as any).foo).toBeInstanceOf(Uint8Array); - }); -}); - -describe('extensions', () => { - test('can encode a 5 byte extension', () => { - const ext = new JsonPackExtension(33, new Uint8Array([1, 2, 3, 4, 5])); - const data = {foo: ext}; - const arr = encode(data); - const res = decode(arr); - expect(res).toEqual(data); - expect((res as any).foo.tag).toBe(33); - expect((res as any).foo.val).toEqual(new Uint8Array([1, 2, 3, 4, 5])); - expect((res as any).foo).toBeInstanceOf(JsonPackExtension); - }); - - test('can encode a 1 byte extension', () => { - const ext = new JsonPackExtension(32, new Uint8Array([5])); - const data = {foo: ext}; - const arr = encode(data); - const res = decode(arr); - expect(res).toEqual(data); - expect((res as any).foo.tag).toBe(32); - expect((res as any).foo.val).toEqual(new Uint8Array([5])); - expect((res as any).foo).toBeInstanceOf(JsonPackExtension); - }); - - test('can encode a 2 byte extension', () => { - const ext = new JsonPackExtension(32, new Uint8Array([5, 0])); - const data = {foo: ext}; - const arr = encode(data); - const res = decode(arr); - expect(res).toEqual(data); - expect((res as any).foo.tag).toBe(32); - expect((res as any).foo.val).toEqual(new Uint8Array([5, 0])); - expect((res as any).foo).toBeInstanceOf(JsonPackExtension); - }); -}); - -describe('pre-computed value', () => { - test('can encode a pre-computed value in an object', () => { - const data = {foo: new JsonPackValue(encode(['gaga']))}; - const arr = encode(data); - expect(arr).toEqual(encode({foo: ['gaga']})); - }); - - test('can encode a pre-computed value in an array', () => { - const data = {foo: [1, new JsonPackValue(encode(['gaga']))]}; - const arr = encode(data); - expect(arr).toEqual(encode({foo: [1, ['gaga']]})); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.overwrite.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.overwrite.spec.ts deleted file mode 100644 index 86638f589c..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.overwrite.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {MsgPackEncoderFast} from '../MsgPackEncoderFast'; -import {MsgPackDecoderFast} from '../MsgPackDecoderFast'; - -const encoder = new MsgPackEncoderFast(); -const decoder = new MsgPackDecoderFast(); -const encode = (x: unknown) => encoder.encode(x); -const decode = (arr: Uint8Array) => decoder.decode(arr); - -test('does not overwrite previous buffer', () => { - const buf1 = encode(true); - const buf2 = encode(false); - const val1 = decode(buf1); - const val2 = decode(buf2); - expect(val1).toBe(true); - expect(val2).toBe(false); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.spec.ts deleted file mode 100644 index f56f70e1d1..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackEncoderFast.spec.ts +++ /dev/null @@ -1,293 +0,0 @@ -import {MsgPackEncoderFast} from '..'; - -const {TextEncoder} = require('util'); -if (!global.TextEncoder) global.TextEncoder = TextEncoder; - -const encoder = new MsgPackEncoderFast(); -const encode = (x: unknown) => encoder.encode(x); - -describe('null', () => { - test('encodes null', () => { - const buf = encode(null); - expect([...new Uint8Array(buf)]).toEqual([0xc0]); - }); -}); - -describe('boolean', () => { - test('encodes false', () => { - const buf = encode(false); - expect([...new Uint8Array(buf)]).toEqual([0xc2]); - }); - - test('encodes true', () => { - const buf = encode(true); - expect([...new Uint8Array(buf)]).toEqual([0xc3]); - }); -}); - -describe('number', () => { - test('encodes positive fixint', () => { - const ints = [0, 1, 2, 0b10, 0b100, 0b1000, 0b10000, 0b100000, 0b1000000, 0x7f]; - for (const int of ints) expect([...new Uint8Array(encode(int))]).toEqual([int]); - }); - - test('encodes negative fixint', () => { - const ints = [-1, -2, -3, -4, -0b11110, -0b11111]; - const res = [ - 0xe0 | (-1 + 0x20), - 0xe0 | (-2 + 0x20), - 0xe0 | (-3 + 0x20), - 0xe0 | (-4 + 0x20), - 0xe0 | (-0b11110 + 0x20), - 0xe0 | (-0b11111 + 0x20), - ]; - for (let i = 0; i < ints.length; i++) expect([...new Uint8Array(encode(ints[i]))]).toEqual([res[i]]); - }); - - test('encodes doubles', () => { - const arr = encode(123.456789123123); - expect(arr.byteLength).toBe(9); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xcb); - expect(view.getFloat64(1)).toBe(123.456789123123); - }); - - // Skipped as due to optimization encoding this as float64 - test.skip('encodes large negative integer', () => { - const arr = encode(-4807526976); - expect(arr.byteLength).toBe(9); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xd3); - expect([...new Uint8Array(arr.buffer)]).toEqual([0xd3, 0xff, 0xff, 0xff, 0xfe, 0xe1, 0x72, 0xf5, 0xc0]); - }); -}); - -describe('string', () => { - test('encodes a zero length string', () => { - const buf = encode(''); - expect(buf.byteLength).toBe(1); - expect([...new Uint8Array(buf)]).toEqual([0b10100000]); - }); - - test('encodes a one char string', () => { - const buf = encode('a'); - expect(buf.byteLength).toBe(2); - expect([...new Uint8Array(buf)]).toEqual([0b10100001, 97]); - }); - - test('encodes a short string', () => { - const buf = encode('foo'); - expect(buf.byteLength).toBe(4); - expect([...new Uint8Array(buf)]).toEqual([0b10100011, 102, 111, 111]); - }); - - // Skipping these as for performance optimization strings are encoded as 4x longer then they could be. - test.skip('encodes 31 char string', () => { - const buf = encode('1234567890123456789012345678901'); - expect(buf.byteLength).toBe(32); - expect([...new Uint8Array(buf)]).toEqual([ - 0b10111111, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 48, 49, - ]); - }); - test.skip('encodes 255 char string', () => { - const buf = encode('a'.repeat(255)); - expect(buf.byteLength).toBe(257); - expect([...new Uint8Array(buf)]).toEqual([ - 0xd9, 255, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, - ]); - }); - test.skip('encodes 0xFFFF char string', () => { - const buf = encode('b'.repeat(0xffff)); - expect(buf.byteLength).toBe(0xffff + 3); - const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - expect(view.getUint8(0)).toBe(0xda); - expect(view.getUint16(1)).toBe(0xffff); - }); - - // Skipping this test as due to optimizations, optimal encoding size is not used. - test.skip('encodes 2000 char string', () => { - const buf = encode('ab'.repeat(1000)); - expect(buf.byteLength).toBe(2003); - const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - expect(view.getUint8(0)).toBe(0xda); - expect(view.getUint16(1)).toBe(2000); - }); - - test('encodes 0xFFFF + 1 char string', () => { - const buf = encode('d'.repeat(0xffff + 1)); - expect(buf.byteLength).toBe(0xffff + 1 + 5); - // const view = new DataView(buf); - // expect(view.getUint8(0)).toBe(0xdb); - // expect(view.getUint32(1)).toBe(0xFFFF + 1); - }); -}); - -describe('array', () => { - test('encodes empty array', () => { - const buf = encode([]); - expect(buf.byteLength).toBe(1); - expect([...new Uint8Array(buf)]).toEqual([0b10010000]); - }); - - test('encodes one element array', () => { - const buf = encode([1]); - expect(buf.byteLength).toBe(2); - expect([...new Uint8Array(buf)]).toEqual([0b10010001, 1]); - }); - - test('encodes three element array', () => { - const buf = encode([1, 2, 3]); - expect(buf.byteLength).toBe(4); - expect([...new Uint8Array(buf)]).toEqual([0b10010011, 1, 2, 3]); - }); - - test('encodes 15 element array', () => { - const arr = '1'.repeat(15).split('').map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(16); - expect([...new Uint8Array(buf)]).toEqual([0b10011111, ...arr]); - }); - - test('encodes 16 element array', () => { - const arr = '2'.repeat(16).split('').map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(19); - expect([...new Uint8Array(buf)]).toEqual([0xdc, 0, 16, ...arr]); - }); - - test('encodes 255 element array', () => { - const arr = '3'.repeat(255).split('').map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(1 + 2 + 255); - expect([...new Uint8Array(buf)]).toEqual([0xdc, 0, 255, ...arr]); - }); - - test('encodes 256 element array', () => { - const arr = '3'.repeat(256).split('').map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(1 + 2 + 256); - expect([...new Uint8Array(buf)]).toEqual([0xdc, 1, 0, ...arr]); - }); - - test('encodes 0xFFFF element array', () => { - const arr = '3'.repeat(0xffff).split('').map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(1 + 2 + 0xffff); - expect([...new Uint8Array(buf)]).toEqual([0xdc, 0xff, 0xff, ...arr]); - }); - - test('encodes 0xFFFF + 1 element array', () => { - const arr = '3' - .repeat(0xffff + 1) - .split('') - .map(Number); - const buf = encode(arr); - expect(buf.byteLength).toBe(1 + 4 + 0xffff + 1); - expect([...new Uint8Array(buf)]).toEqual([0xdd, 0, 1, 0, 0, ...arr]); - }); -}); - -describe('object', () => { - test('encodes empty object', () => { - const buf = encode({}); - expect(buf.byteLength).toBe(1); - expect([...new Uint8Array(buf)]).toEqual([0b10000000]); - }); - - test('encodes object with one key', () => { - const buf = encode({a: 1}); - expect(buf.byteLength).toBe(1 + 2 + 1); - expect([...new Uint8Array(buf)]).toEqual([0b10000001, 0b10100001, 97, 1]); - }); - - test('encodes object with 15 keys', () => { - const arr = encode({ - 1: 1, - 2: 1, - 3: 1, - 4: 1, - 5: 1, - 6: 1, - 7: 1, - 8: 1, - 9: 1, - 10: 1, - 11: 1, - 12: 1, - 13: 1, - 14: 1, - 15: 1, - }); - expect(arr.byteLength).toBe(1 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 4 + 4 + 4 + 4 + 4 + 4); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0b10001111); - }); - - test('encodes object with 16 keys', () => { - const arr = encode({ - 1: 1, - 2: 1, - 3: 1, - 4: 1, - 5: 1, - 6: 1, - 7: 1, - 8: 1, - 9: 1, - 10: 1, - 11: 1, - 12: 1, - 13: 1, - 14: 1, - 15: 1, - 16: 1, - }); - expect(arr.byteLength).toBe(1 + 2 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xde); - expect(view.getUint16(1)).toBe(16); - }); - - test('encodes object with 255 keys', () => { - const obj: any = {}; - for (let i = 0; i < 255; i++) obj[String(i)] = i; - const arr = encode(obj); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xde); - expect(view.getUint16(1)).toBe(255); - expect(view.getUint8(3)).toBe(0b10100001); - expect(view.getUint8(4)).toBe(48); - }); - - test('encodes object with 0xFFFF keys', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff; i++) obj[String(i)] = i; - const arr = encode(obj); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xde); - expect(view.getUint16(1)).toBe(0xffff); - expect(view.getUint8(3)).toBe(0b10100001); - expect(view.getUint8(4)).toBe(48); - }); - - test('encodes object with 0xFFFF + 1 keys', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff + 1; i++) obj[String(i)] = i; - const arr = encode(obj); - const view = new DataView(arr.buffer, arr.byteOffset, arr.byteLength); - expect(view.getUint8(0)).toBe(0xdf); - expect(view.getUint32(1)).toBe(0xffff + 1); - expect(view.getUint8(5)).toBe(0b10100001); - expect(view.getUint8(6)).toBe(48); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackEncoderStable.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackEncoderStable.spec.ts deleted file mode 100644 index 3a36b7f761..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackEncoderStable.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {MsgPackEncoderStable} from '../MsgPackEncoderStable'; -import {MsgPackDecoderFast} from '../MsgPackDecoderFast'; - -const encoder = new MsgPackEncoderStable(); -const encode = (x: unknown) => encoder.encode(x); -const decoder = new MsgPackDecoderFast(); -const decode = (a: Uint8Array) => decoder.decode(a); - -test('encodes object the same regardless of key order', () => { - const data1 = {a: 1, b: 2}; - const data2 = {b: 2, a: 1}; - const arr1 = encode(data1); - const arr2 = encode(data2); - expect(arr1).toStrictEqual(arr2); - expect(decode(arr1)).toStrictEqual(decode(arr2)); - expect(arr1).toMatchInlineSnapshot(` - Uint8Array [ - 130, - 161, - 97, - 1, - 161, - 98, - 2, - ] - `); -}); diff --git a/src/json-pack/msgpack/__tests__/MsgPackToJsonConverter.spec.ts b/src/json-pack/msgpack/__tests__/MsgPackToJsonConverter.spec.ts deleted file mode 100644 index 20db34cf86..0000000000 --- a/src/json-pack/msgpack/__tests__/MsgPackToJsonConverter.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {documents} from '../../../__tests__/json-documents'; -import {MsgPackToJsonConverter} from '../MsgPackToJsonConverter'; -import {MsgPackEncoder} from '../MsgPackEncoder'; - -const encoder = new MsgPackEncoder(); -const converter = new MsgPackToJsonConverter(); - -for (const doc of documents) { - (doc.only ? test.only : test)(doc.name, () => { - const msgpack = encoder.encode(doc.json); - const json = converter.convert(msgpack); - const parsed = JSON.parse(json); - expect(parsed).toStrictEqual(doc.json); - }); -} diff --git a/src/json-pack/msgpack/__tests__/codec.spec.ts b/src/json-pack/msgpack/__tests__/codec.spec.ts deleted file mode 100644 index a334fa3707..0000000000 --- a/src/json-pack/msgpack/__tests__/codec.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {MsgPackEncoderFast, MsgPackDecoderFast} from '..'; -import {documents} from '../../../__tests__/json-documents'; - -const encoder = new MsgPackEncoderFast(); -const decoder = new MsgPackDecoderFast(); -const encode = (x: unknown) => encoder.encode(x); -const decode = (x: Uint8Array) => decoder.decode(x); - -for (const t of documents) { - test(t.name, () => { - const buf = encode(t.json); - const res = decode(buf); - expect(res).toEqual(t.json); - }); -} diff --git a/src/json-pack/msgpack/__tests__/decode.spec.ts b/src/json-pack/msgpack/__tests__/decode.spec.ts deleted file mode 100644 index 0c5be26c1f..0000000000 --- a/src/json-pack/msgpack/__tests__/decode.spec.ts +++ /dev/null @@ -1,239 +0,0 @@ -import {MsgPackEncoderFast, MsgPackDecoderFast} from '..'; - -const encoder = new MsgPackEncoderFast(); -const encode = (x: unknown) => encoder.encode(x); -const decoder = new MsgPackDecoderFast(); -const decode = (a: Uint8Array) => decoder.decode(a); - -describe('null', () => { - test('can decode null', () => { - const buf = encode(null); - const res = decode(buf); - expect(res).toBe(null); - }); -}); - -describe('boolean', () => { - test('can decode false', () => { - const buf = encode(false); - const res = decode(buf); - expect(res).toBe(false); - }); - - test('can decode true', () => { - const buf = encode(true); - const res = decode(buf); - expect(res).toBe(true); - }); -}); - -describe('number', () => { - test('can decode positive fixint', () => { - const buf = encode(123); - const res = decode(buf); - expect(res).toBe(123); - }); - - test('can decode 0', () => { - const buf = encode(0); - const res = decode(buf); - expect(res).toBe(0); - }); - - test('can decode negative fixint', () => { - const buf = encode(-1); - const res = decode(buf); - expect(res).toBe(-1); - }); - - test('can decode negative fixint - 2', () => { - const buf = encode(-32); - const res = decode(buf); - expect(res).toBe(-32); - }); - - test('can decode double', () => { - const buf = encode(3456.12345678902234); - const res = decode(buf); - expect(res).toBe(3456.12345678902234); - }); - - test('can decode 8 byte negative int', () => { - const buf = encode(-4807526976); - const res = decode(buf); - expect(res).toBe(-4807526976); - }); -}); - -describe('string', () => { - test('can decode empty string', () => { - const buf = encode(''); - const res = decode(buf); - expect(res).toBe(''); - }); - - test('can decode short string', () => { - const buf = encode('abc'); - const res = decode(buf); - expect(res).toBe('abc'); - }); - - test('can decode 31 char string', () => { - const buf = encode('1234567890123456789012345678901'); - const res = decode(buf); - expect(res).toBe('1234567890123456789012345678901'); - }); - - test('can decode 32 char string', () => { - const buf = encode('12345678901234567890123456789012'); - const res = decode(buf); - expect(res).toBe('12345678901234567890123456789012'); - }); - - test('can decode 255 char string', () => { - const str = 'a'.repeat(255); - const buf = encode(str); - const res = decode(buf); - expect(res).toBe(str); - }); - - test('can decode 256 char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf); - expect(res).toBe(str); - }); - - test('can decode 0xFFFF char string', () => { - const str = 'a'.repeat(256); - const buf = encode(str); - const res = decode(buf); - expect(res).toBe(str); - }); - - test('can decode 0xFFFF + 1 char string', () => { - const str = 'a'.repeat(0xffff + 1); - const buf = encode(str); - const res = decode(buf); - expect(res).toBe(str); - }); -}); - -describe('array', () => { - test('can decode empty array', () => { - const buf = encode([]); - const res = decode(buf); - expect(res).toEqual([]); - }); - - test('can decode one element array', () => { - const buf = encode(['abc']); - const res = decode(buf); - expect(res).toEqual(['abc']); - }); - - test('can decode 15 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - const res = decode(buf); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - }); - - test('can decode 16 element array', () => { - const buf = encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - const res = decode(buf); - expect(res).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - }); - - test('can decode 255 element array', () => { - const arr = '3'.repeat(256).split('').map(Number); - const buf = encode(arr); - const res = decode(buf); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF element array', () => { - const arr = '3'.repeat(0xffff).split('').map(Number); - const buf = encode(arr); - const res = decode(buf); - expect(res).toEqual(arr); - }); - - test('can decode 0xFFFF + 1 element array', () => { - const arr = '3'.repeat(0xffff + 1).split(''); - const buf = encode(arr); - const res = decode(buf); - expect(res).toEqual(arr); - }); -}); - -describe('object', () => { - test('can decode empty object', () => { - const obj = {}; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode simple object', () => { - const obj = {foo: 'bar'}; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 15 key object', () => { - const obj: any = {}; - for (let i = 0; i < 15; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 16 key object', () => { - const obj: any = {}; - for (let i = 0; i < 16; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 32 key object', () => { - const obj: any = {}; - for (let i = 0; i < 32; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 255 key object', () => { - const obj: any = {}; - for (let i = 0; i < 255; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 256 key object', () => { - const obj: any = {}; - for (let i = 0; i < 256; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); - - test('can decode 0xFFFF + 1 key object', () => { - const obj: any = {}; - for (let i = 0; i < 0xffff + 1; i++) obj[String(i)] = i; - const buf = encode(obj); - const res = decode(buf); - expect(res).toEqual(obj); - }); -}); diff --git a/src/json-pack/msgpack/__tests__/fuzzing.spec.ts b/src/json-pack/msgpack/__tests__/fuzzing.spec.ts deleted file mode 100644 index 403160dcce..0000000000 --- a/src/json-pack/msgpack/__tests__/fuzzing.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {encode} from '@msgpack/msgpack'; -import {RandomJson} from '../../../json-random'; -import {MsgPackEncoderFast} from '../MsgPackEncoderFast'; -import {MsgPackDecoderFast} from '../MsgPackDecoderFast'; - -const encoder1 = new MsgPackEncoderFast(); -const decoder1 = new MsgPackDecoderFast(); - -test('fuzzing', () => { - for (let i = 0; i < 200; i++) { - const value = RandomJson.generate(); - const encoded1 = encoder1.encode(value); - const decoded1 = decoder1.decode(encoded1); - const encoded2 = encode(value); - const decoded2 = decoder1.decode(encoded2); - expect(decoded1).toStrictEqual(value); - expect(decoded2).toStrictEqual(value); - } -}); diff --git a/src/json-pack/msgpack/__tests__/numbers.spec.ts b/src/json-pack/msgpack/__tests__/numbers.spec.ts deleted file mode 100644 index 90c1a46b49..0000000000 --- a/src/json-pack/msgpack/__tests__/numbers.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import {MsgPackEncoderFast, MsgPackDecoderFast} from '..'; - -const encoder = new MsgPackEncoderFast(); -const encode = (x: unknown) => encoder.encode(x); -const decoder = new MsgPackDecoderFast(); -const decode = (a: Uint8Array) => decoder.decode(a); - -test('unsigned integers', () => { - let x1 = 0; - let x2 = 1; - for (let i = 0; i < 10000000000000000000; ) { - i = x1 + x2; - const buf = encode(i); - const res = decode(buf); - expect(res).toBe(i); - [x1, x2] = [x2, i]; - } -}); - -test('unsigned integers - 2', () => { - let x = 0; - for (let i = 0; i < 10000; i++) { - const buf = encode(x); - const res = decode(buf); - expect(res).toBe(x); - x += Math.round(1000 * Math.random()); - } -}); - -test('negative integers', () => { - let x1 = 0; - let x2 = -1; - for (let i = 0; i > -1000000000000000000; ) { - i = x1 + x2; - const buf = encode(i); - const res = decode(buf); - expect(res).toBe(i); - [x1, x2] = [x2, i]; - } -}); - -test('floats', () => { - let x = Math.random(); - for (let i = 0; i < 1000; i++) { - const buf = encode(x); - const res = decode(buf); - expect(res).toBe(x); - x = x * Math.random(); - } -}); - -test('floats - 2', () => { - let x = 1.001; - for (let i = 0; i < 10000; i++) { - const buf = encode(x); - const res = decode(buf); - expect(res).toBe(x); - x *= 1 + Math.random(); - } -}); - -test('floats - 3', () => { - let x = 0.1; - for (let i = 0; i < 10000; i++) { - const buf = encode(x); - const res = decode(buf); - expect(res).toBe(x); - x += 0.1; - } -}); - -test('floats - 4', () => { - let x = Math.random(); - for (let i = 0; i < 10000; i++) { - const buf = encode(x); - const res = decode(buf); - expect(res).toBe(x); - x += Math.random(); - } -}); diff --git a/src/json-pack/msgpack/__tests__/shallow-read.genShallowRead.spec.ts b/src/json-pack/msgpack/__tests__/shallow-read.genShallowRead.spec.ts deleted file mode 100644 index bc85687d59..0000000000 --- a/src/json-pack/msgpack/__tests__/shallow-read.genShallowRead.spec.ts +++ /dev/null @@ -1,130 +0,0 @@ -import {genShallowReader} from '../shallow-read'; -import {MsgPackEncoder} from '../MsgPackEncoder'; -import {MsgPackDecoder} from '../MsgPackDecoder'; -import {Path} from '../../../json-pointer'; - -const assetShallowRead = (doc: unknown, path: Path): void => { - const encoder = new MsgPackEncoder(); - const encoded = encoder.encode(doc); - const decoder = new MsgPackDecoder(); - decoder.reader.reset(encoded); - const res1 = decoder.find(path).reader.x; - // console.log(res1); - const fn = genShallowReader(path); - // console.log(fn.toString()); - decoder.reader.reset(encoded); - const res2 = fn(decoder); - // console.log(res2); - expect(res1).toBe(res2); -}; - -describe('genShallowRead', () => { - test('first-level object', () => { - const doc = { - bar: {}, - baz: 123, - gg: true, - }; - assetShallowRead(doc, ['bar']); - assetShallowRead(doc, ['baz']); - assetShallowRead(doc, ['gg']); - }); - - test('second-level object', () => { - const doc = { - a: { - bar: {}, - baz: 123, - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - assetShallowRead(doc, ['a']); - assetShallowRead(doc, ['a', 'bar']); - assetShallowRead(doc, ['a', 'baz']); - assetShallowRead(doc, ['a', 'gg']); - assetShallowRead(doc, ['b', 'mmmm']); - assetShallowRead(doc, ['b', 'mmmm', 's']); - assetShallowRead(doc, ['end']); - }); - - test('first-level array', () => { - const doc = [0]; - assetShallowRead(doc, [0]); - }); - - test('first-level array - 2', () => { - const doc = [1234, 'asdf', {}, null, false]; - assetShallowRead(doc, [0]); - assetShallowRead(doc, [1]); - assetShallowRead(doc, [2]); - assetShallowRead(doc, [3]); - assetShallowRead(doc, [4]); - }); - - test('throws when selector is out of bounds of array', () => { - const doc = [1234, 'asdf', {}, null, false]; - expect(() => assetShallowRead(doc, [5])).toThrowError(); - }); - - test('can read from complex nested document', () => { - const doc = { - a: { - bar: [ - { - a: 1, - 2: true, - asdf: false, - }, - 5, - ], - baz: ['a', 'b', 123], - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - assetShallowRead(doc, ['a']); - assetShallowRead(doc, ['a', 'bar', 0]); - assetShallowRead(doc, ['a', 'bar', 1]); - assetShallowRead(doc, ['a', 'bar', 0, 'a']); - assetShallowRead(doc, ['a', 'bar', 0, '2']); - assetShallowRead(doc, ['a', 'bar', 0, 'asdf']); - assetShallowRead(doc, ['b']); - assetShallowRead(doc, ['b', 'mmmm']); - assetShallowRead(doc, ['b', 'mmmm', 's']); - assetShallowRead(doc, ['end']); - }); - - test('should throw when key does not exist', () => { - const doc = { - a: { - bar: {}, - baz: 123, - gg: true, - }, - b: { - mmmm: { - s: true, - }, - }, - end: null, - }; - const encoder = new MsgPackEncoder(); - const encoded = encoder.encode(doc); - const decoder = new MsgPackDecoder(); - decoder.reader.reset(encoded); - const fn = genShallowReader(['asdf']); - // console.log(fn.toString()); - expect(() => fn(decoder)).toThrowError(); - }); -}); diff --git a/src/json-pack/msgpack/constants.ts b/src/json-pack/msgpack/constants.ts deleted file mode 100644 index 8e9e5aa2bb..0000000000 --- a/src/json-pack/msgpack/constants.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const enum MSGPACK { - NULL = 0xc0, - UNDEFINED = 0xc1, - FALSE = 0xc2, - TRUE = 0xc3, -} diff --git a/src/json-pack/msgpack/index.ts b/src/json-pack/msgpack/index.ts deleted file mode 100644 index f63069b61a..0000000000 --- a/src/json-pack/msgpack/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * # `json-pack` MessagePack` - * - * Library for encoding and decoding JavaScript native structures to MessagePack - * format. - * - * Use `Encoder` to encode plain JSON values. - * - * ```ts - * import {Encoder, Decoder} from 'json-joy/{lib,es6,esm}/json-pack'; - * - * const encoder = new Encoder(); - * const decoder = new Decoder(); - * const buffer = encoder.encode({foo: 'bar'}); - * const obj = decoder.decode(buffer); - * - * console.log(obj); // { foo: 'bar' } - * ``` - * - * For more: - * - * - Use {@link Encoder} to encode only JSON values. - * - Use {@link EncoderFull} to also encode binary data, extensions and pre-computed MessagePack buffers. - * - To encode binary data use `Uint8Array`. - * - To encode an extension use {@link JsonPackExtension}. - * - To encode a pre-computed MessagePack value use {@link JsonPackValue}. - * - * @module - */ - -export {MsgPackEncoderFast} from './MsgPackEncoderFast'; -export {MsgPackEncoder} from './MsgPackEncoder'; -export {MsgPackEncoderStable} from './MsgPackEncoderStable'; -export {MsgPackDecoderFast} from './MsgPackDecoderFast'; -export {MsgPackToJsonConverter} from './MsgPackToJsonConverter'; -export {JsonPackValue} from '../JsonPackValue'; -export {JsonPackExtension} from '../JsonPackExtension'; -export * from './types'; diff --git a/src/json-pack/msgpack/shallow-read.ts b/src/json-pack/msgpack/shallow-read.ts deleted file mode 100644 index 5ecb09832e..0000000000 --- a/src/json-pack/msgpack/shallow-read.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {Path} from '../../json-pointer'; -import {Codegen} from '../../util/codegen/Codegen'; -import type {MsgPackDecoder} from './MsgPackDecoder'; - -type Decoder = Pick; - -type Fn = (decoder: Decoder) => number; - -const toUtf8 = (str: string) => { - const arr: number[] = []; - const length = str.length; - let curr = 0; - while (curr < length) { - let value = str.charCodeAt(curr++); - if ((value & 0xffffff80) === 0) { - arr.push(value); - continue; - } else if ((value & 0xfffff800) === 0) { - arr.push(((value >> 6) & 0x1f) | 0xc0); - } else { - if (value >= 0xd800 && value <= 0xdbff) { - if (curr < length) { - const extra = str.charCodeAt(curr); - if ((extra & 0xfc00) === 0xdc00) { - curr++; - value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; - } - } - } - if ((value & 0xffff0000) === 0) { - arr.push(((value >> 12) & 0x0f) | 0xe0); - arr.push(((value >> 6) & 0x3f) | 0x80); - } else { - arr.push(((value >> 18) & 0x07) | 0xf0); - arr.push(((value >> 12) & 0x3f) | 0x80); - arr.push(((value >> 6) & 0x3f) | 0x80); - } - } - arr.push((value & 0x3f) | 0x80); - } - return arr; -}; - -export const genShallowReader = (path: Path): Fn => { - const codegen = new Codegen({ - args: ['dec'], - name: 'readShallow', - prologue: 'var r = dec.reader;', - epilogue: 'return r.x;', - }); - - for (let i = 0; i < path.length; i++) { - const step = path[i]; - switch (typeof step) { - case 'string': { - const rObj = codegen.getRegister(); - const rIter = codegen.getRegister(); - const rFound = codegen.getRegister(); - codegen.js(/* js */ `var ${rObj} = dec.readObjHdr();`); - codegen.js(/* js */ `var ${rFound} = false;`); - codegen.js(`for(var ${rIter} = 0; ${rIter} < ${rObj}; ${rIter}++) {`); - const utf8Arr = toUtf8(step); - const length = utf8Arr.length; - const rKey = codegen.getRegister(); - codegen.js(/* js */ `var ${rKey} = dec.readStrHdr();`); - codegen.js(/* js */ `if (${rKey} !== ${length}) { r.x += ${rKey}; dec.skipAny(); continue; };`); - while (utf8Arr.length > 0) { - if (utf8Arr.length >= 4) { - const word = utf8Arr.splice(0, 4); - const utf8Chunk = '0x' + word.map((x) => x.toString(16)).join(''); - codegen.js( - `if (r.u32() !== ${utf8Chunk}) { ${ - utf8Arr.length ? `r.x += ${utf8Arr.length}; ` : '' - }dec.skipAny(); continue; }`, - ); - } else if (utf8Arr.length >= 2) { - const word = utf8Arr.splice(0, 2); - const utf8Chunk = '0x' + word.map((x) => x.toString(16)).join(''); - codegen.js( - `if (r.u16() !== ${utf8Chunk}) { ${ - utf8Arr.length ? `r.x += ${utf8Arr.length}; ` : '' - }dec.skipAny(); continue; }`, - ); - } else { - const [octet] = utf8Arr.splice(0, 1); - codegen.js( - `if (r.u8() !== ${octet}) { ${ - utf8Arr.length ? `r.x += ${utf8Arr.length}; ` : '' - }dec.skipAny(); continue; }`, - ); - } - } - codegen.js(`${rFound} = true;`); - codegen.js(`break;`); - codegen.js(`}`); - codegen.js(`if (!${rFound}) throw new Error('KEY_NOT_FOUND');`); - break; - } - case 'number': { - const rObj = codegen.getRegister(); - codegen.js(/* js */ `var ${rObj} = dec.readArrHdr();`); - codegen.js(/* js */ `if(${rObj} <= ${step}) throw new Error('INDEX_OUT_OF_BOUNDS');`); - for (let i = 0; i < step; i++) codegen.js(/* js */ `dec.skipAny();`); - break; - } - default: { - throw new Error('INVALID_PATH_STEP'); - } - } - } - - return codegen.compile(); -}; diff --git a/src/json-pack/msgpack/types.ts b/src/json-pack/msgpack/types.ts deleted file mode 100644 index 080434af3d..0000000000 --- a/src/json-pack/msgpack/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type {IWriter, IWriterGrowable} from '../../util/buffers'; - -export type MsgPack = Uint8Array & {__BRAND__: 'msgpack'; __TYPE__: T}; - -/** @deprecated */ -export interface IMessagePackEncoder { - writer: IWriter & IWriterGrowable; - encodeAny(value: unknown): void; - encodeNumber(num: number): void; - encodeString(str: string): void; - encodeArray(arr: unknown[]): void; - encodeArrayHeader(length: number): void; - encodeObject(obj: Record): void; - encodeObjectHeader(length: number): void; -} diff --git a/src/json-pack/msgpack/util.ts b/src/json-pack/msgpack/util.ts deleted file mode 100644 index eaaa9afce0..0000000000 --- a/src/json-pack/msgpack/util.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {MsgPackEncoderFast} from './MsgPackEncoderFast'; -import {MsgPackEncoder} from './MsgPackEncoder'; -import {MsgPackDecoderFast} from './MsgPackDecoderFast'; -import {MsgPack} from './types'; - -export const encoder = new MsgPackEncoderFast(); -export const encoderFull = new MsgPackEncoder(); -export const decoder = new MsgPackDecoderFast(); - -export const encode = (data: T): MsgPack => encoder.encode(data) as MsgPack; -export const encodeFull = (data: T): MsgPack => encoderFull.encode(data) as MsgPack; -export const decode = (blob: MsgPack): T => decoder.decode(blob) as T; - -export type {MsgPack}; diff --git a/src/json-pack/resp/README.md b/src/json-pack/resp/README.md deleted file mode 100644 index fe3e24eac9..0000000000 --- a/src/json-pack/resp/README.md +++ /dev/null @@ -1 +0,0 @@ -# RESP v2 and RESP3 codecs diff --git a/src/json-pack/resp/RespDecoder.ts b/src/json-pack/resp/RespDecoder.ts deleted file mode 100644 index 54cb42997a..0000000000 --- a/src/json-pack/resp/RespDecoder.ts +++ /dev/null @@ -1,422 +0,0 @@ -import {Reader} from '../../util/buffers/Reader'; -import {RESP} from './constants'; -import {RespAttributes, RespPush} from './extensions'; -import type {IReader, IReaderResettable} from '../../util/buffers'; -import type {BinaryJsonDecoder, PackValue} from '../types'; -import {isUtf8} from '../../util/buffers/utf8/isUtf8'; - -export class RespDecoder - implements BinaryJsonDecoder -{ - /** - * When set to true, the decoder will attempt to decode RESP Bulk strings - * (which are binary strings, i.e. Uint8Array) as UTF-8 strings. If the - * string is not valid UTF-8, it will be returned as a Uint8Array. - * - * You can toggle this setting at any time, before each call to `decode()` - * or `read()`, or other methods. - */ - public tryUtf8 = false; - - public constructor(public reader: R = new Reader() as any) {} - - public read(uint8: Uint8Array): PackValue { - this.reader.reset(uint8); - return this.val() as PackValue; - } - - /** @deprecated */ - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.val(); - } - - // -------------------------------------------------------- Any value reading - - public val(): unknown { - const reader = this.reader; - const type = reader.u8(); - switch (type) { - case RESP.INT: - return this.readInt(); - case RESP.FLOAT: - return this.readFloat(); - case RESP.STR_SIMPLE: - return this.readStrSimple(); - case RESP.STR_BULK: - return this.readStrBulk(); - case RESP.BOOL: - return this.readBool(); - case RESP.NULL: - return reader.skip(2), null; - case RESP.OBJ: - return this.readObj(); - case RESP.ARR: - return this.readArr(); - case RESP.STR_VERBATIM: - return this.readStrVerbatim(); - case RESP.PUSH: - return new RespPush(this.readArr() || []); - case RESP.BIG: - return this.readBigint(); - case RESP.SET: - return this.readSet(); - case RESP.ERR_SIMPLE: - return this.readErrSimple(); - case RESP.ERR_BULK: - return this.readErrBulk(); - case RESP.ATTR: - return new RespAttributes(this.readObj()); - } - throw new Error('UNKNOWN_TYPE'); - } - - protected readLength(): number { - const reader = this.reader; - let number: number = 0; - while (true) { - const c = reader.u8(); - if (c === RESP.R) return reader.skip(1), number; - number = number * 10 + (c - 48); - } - } - - public readCmd(): [cmd: string, ...args: Uint8Array[]] { - const reader = this.reader; - const type = reader.u8(); - if (type !== RESP.ARR) throw new Error('INVALID_COMMAND'); - const c = reader.peak(); - if (c === RESP.MINUS) throw new Error('INVALID_COMMAND'); - const length = this.readLength(); - if (length === 0) throw new Error('INVALID_COMMAND'); - const cmd = this.readAsciiAsStrBulk().toUpperCase(); - const args: [cmd: string, ...args: Uint8Array[]] = [cmd]; - this.tryUtf8 = false; - for (let i = 1; i < length; i++) { - const type = reader.u8(); - if (type !== RESP.STR_BULK) throw new Error('INVALID_COMMAND'); - args.push(this.readStrBulk() as Uint8Array); - } - return args; - } - - // ---------------------------------------------------------- Boolean reading - - public readBool(): boolean { - const reader = this.reader; - const c = reader.u8(); - reader.skip(2); // Skip "\r\n". - return c === 116; // t - } - - // ----------------------------------------------------------- Number reading - - public readInt(): number { - const reader = this.reader; - let negative = false; - let c = reader.u8(); - let number: number = 0; - if (c === RESP.MINUS) { - negative = true; - } else if (c !== RESP.PLUS) number = c - 48; - while (true) { - c = reader.u8(); - if (c === RESP.R) { - reader.skip(1); // Skip "\n". - return negative ? -number : number; - } - number = number * 10 + (c - 48); - } - } - - public readFloat(): number { - const reader = this.reader; - const x = reader.x; - while (true) { - const c = reader.u8(); - if (c !== RESP.R) continue; - const length = reader.x - x - 1; - reader.x = x; - const str = reader.ascii(length); - switch (length) { - case 3: - switch (str) { - case 'inf': - return reader.skip(2), Infinity; - case 'nan': - return reader.skip(2), NaN; - } - break; - case 4: - if (str === '-inf') { - return reader.skip(2), -Infinity; - } - break; - } - reader.skip(2); // Skip "\n". - return Number(str); - } - } - - public readBigint(): bigint { - const reader = this.reader; - const x = reader.x; - while (true) { - const c = reader.u8(); - if (c !== RESP.R) continue; - const length = reader.x - x; - reader.x = x; - const str = reader.ascii(length); - reader.skip(1); // Skip "\n". - return BigInt(str); - } - } - - // ----------------------------------------------------------- String reading - - public readStrSimple(): string { - const reader = this.reader; - const x = reader.x; - while (true) { - const c = reader.u8(); - if (c !== RESP.R) continue; - const size = reader.x - x - 1; - reader.x = x; - const str = reader.utf8(size); - reader.skip(2); // Skip "\r\n". - return str; - } - } - - public readStrBulk(): Uint8Array | string | null { - const reader = this.reader; - if (reader.peak() === RESP.MINUS) { - reader.skip(4); // Skip "-1\r\n". - return null; - } - const length = this.readLength(); - let res: Uint8Array | string; - if (this.tryUtf8 && isUtf8(reader.uint8, reader.x, length)) res = reader.utf8(length); - else res = reader.buf(length); - reader.skip(2); // Skip "\r\n". - return res; - } - - public readAsciiAsStrBulk(): string { - const reader = this.reader; - reader.skip(1); // Skip "$". - const length = this.readLength(); - const buf = reader.ascii(length); - reader.skip(2); // Skip "\r\n". - return buf; - } - - public readStrVerbatim(): string | Uint8Array { - const reader = this.reader; - const length = this.readLength(); - const u32 = reader.u32(); - const isTxt = u32 === 1954051130; // "txt:" - if (isTxt) { - const str = reader.utf8(length - 4); - reader.skip(2); // Skip "\r\n". - return str; - } - const buf = reader.buf(length - 4); - reader.skip(2); // Skip "\r\n". - return buf; - } - - // ------------------------------------------------------------ Error reading - - public readErrSimple(): Error { - const reader = this.reader; - const x = reader.x; - while (true) { - const c = reader.u8(); - if (c !== RESP.R) continue; - const size = reader.x - x - 1; - reader.x = x; - const str = reader.utf8(size); - reader.skip(2); // Skip "\r\n". - return new Error(str); - } - } - - public readErrBulk(): Error { - const reader = this.reader; - const length = this.readLength(); - const message = reader.utf8(length); - reader.skip(2); // Skip "\r\n". - return new Error(message); - } - - // ------------------------------------------------------------ Array reading - - public readArr(): unknown[] | null { - const reader = this.reader; - const c = reader.peak(); - if (c === RESP.MINUS) { - reader.skip(4); // Skip "-1\r\n". - return null; - } - const length = this.readLength(); - const arr: unknown[] = []; - for (let i = 0; i < length; i++) arr.push(this.val()); - return arr; - } - - public readSet(): Set { - const length = this.readLength(); - const set = new Set(); - for (let i = 0; i < length; i++) set.add(this.val()); - return set; - } - - // ----------------------------------------------------------- Object reading - - public readObj(): Record { - const length = this.readLength(); - const obj: Record = {}; - for (let i = 0; i < length; i++) { - const key = this.val() + ''; - obj[key] = this.val(); - } - return obj; - } - - // ----------------------------------------------------------------- Skipping - - public skipN(n: number): void { - for (let i = 0; i < n; i++) this.skipAny(); - } - - public skipAny(): void { - const reader = this.reader; - const type = reader.u8(); - switch (type) { - case RESP.INT: - return this.skipInt(); - case RESP.FLOAT: - return this.skipFloat(); - case RESP.STR_SIMPLE: - return this.skipStrSimple(); - case RESP.STR_BULK: - return this.skipStrBulk(); - case RESP.BOOL: - return this.skipBool(); - case RESP.NULL: - return reader.skip(2); - case RESP.OBJ: - return this.skipObj(); - case RESP.ARR: - return this.skipArr(); - case RESP.STR_VERBATIM: - return this.skipStrVerbatim(); - case RESP.PUSH: - return this.skipArr(); - case RESP.BIG: - return this.skipBigint(); - case RESP.SET: - return this.skipSet(); - case RESP.ERR_SIMPLE: - return this.skipErrSimple(); - case RESP.ERR_BULK: - return this.skipErrBulk(); - case RESP.ATTR: - return this.skipObj(); - } - throw new Error('UNKNOWN_TYPE'); - } - - public skipBool(): void { - this.reader.skip(3); - } - - public skipInt(): void { - const reader = this.reader; - while (true) { - if (reader.u8() !== RESP.R) continue; - reader.skip(1); // Skip "\n". - return; - } - } - - public skipFloat(): void { - const reader = this.reader; - while (true) { - if (reader.u8() !== RESP.R) continue; - reader.skip(1); // Skip "\n". - return; - } - } - - public skipBigint(): void { - const reader = this.reader; - while (true) { - if (reader.u8() !== RESP.R) continue; - reader.skip(1); // Skip "\n". - return; - } - } - - public skipStrSimple(): void { - const reader = this.reader; - while (true) { - if (reader.u8() !== RESP.R) continue; - reader.skip(1); // Skip "\n". - return; - } - } - - public skipStrBulk(): void { - const reader = this.reader; - if (reader.peak() === RESP.MINUS) { - reader.skip(4); // Skip "-1\r\n". - return; - } - reader.skip(this.readLength() + 2); // Skip "\r\n". - } - - public skipStrVerbatim(): void { - const length = this.readLength(); - this.reader.skip(length + 2); // Skip "\r\n". - } - - public skipErrSimple(): void { - const reader = this.reader; - while (true) { - if (reader.u8() !== RESP.R) continue; - reader.skip(1); // Skip "\n". - return; - } - } - - public skipErrBulk(): void { - const length = this.readLength(); - this.reader.skip(length + 2); // Skip "\r\n". - } - - public skipArr(): void { - const reader = this.reader; - const c = reader.peak(); - if (c === RESP.MINUS) { - reader.skip(4); // Skip "-1\r\n". - return; - } - const length = this.readLength(); - for (let i = 0; i < length; i++) this.skipAny(); - } - - public skipSet(): void { - const length = this.readLength(); - for (let i = 0; i < length; i++) this.skipAny(); - } - - public skipObj(): void { - const length = this.readLength(); - for (let i = 0; i < length; i++) { - this.skipAny(); - this.skipAny(); - } - } -} diff --git a/src/json-pack/resp/RespEncoder.ts b/src/json-pack/resp/RespEncoder.ts deleted file mode 100644 index b534c2ac29..0000000000 --- a/src/json-pack/resp/RespEncoder.ts +++ /dev/null @@ -1,503 +0,0 @@ -import {Writer} from '../../util/buffers/Writer'; -import {RESP} from './constants'; -import {utf8Size} from '../../util/strings/utf8'; -import {RespAttributes, RespPush, RespVerbatimString} from './extensions'; -import {JsonPackExtension} from '../JsonPackExtension'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder, StreamingBinaryJsonEncoder, TlvBinaryJsonEncoder} from '../types'; -import type {Slice} from '../../util/buffers/Slice'; - -const REG_RN = /[\r\n]/; -const isSafeInteger = Number.isSafeInteger; - -/** - * Implements RESP3 encoding. - */ -export class RespEncoder - implements BinaryJsonEncoder, StreamingBinaryJsonEncoder, TlvBinaryJsonEncoder -{ - constructor(public readonly writer: W = new Writer() as any) {} - - public encode(value: unknown): Uint8Array { - this.writeAny(value); - return this.writer.flush(); - } - - public encodeToSlice(value: unknown): Slice { - this.writeAny(value); - return this.writer.flushSlice(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'boolean': - return this.writeBoolean(value); - case 'object': { - if (!value) return this.writeNull(); - if (value instanceof Array) return this.writeArr(value); - if (value instanceof Uint8Array) return this.writeBin(value); - if (value instanceof Error) return this.writeErr(value.message); - if (value instanceof Set) return this.writeSet(value); - if (value instanceof JsonPackExtension) { - if (value instanceof RespPush) return this.writePush(value.val); - if (value instanceof RespVerbatimString) return this.writeVerbatimStr('txt', value.val); - if (value instanceof RespAttributes) return this.writeAttr(value.val); - } - return this.writeObj(value as Record); - } - case 'undefined': - return this.writeUndef(); - case 'bigint': - return this.writeBigInt(value); - default: - return this.writeUnknown(value); - } - } - - protected writeLength(length: number): void { - const writer = this.writer; - if (length < 100) { - if (length < 10) { - writer.u8(length + 48); - return; - } - const octet1 = length % 10; - const octet2 = (length - octet1) / 10; - writer.u16(((octet2 + 48) << 8) + octet1 + 48); - return; - } - let digits = 1; - let pow = 10; - while (length >= pow) { - digits++; - pow *= 10; - } - writer.ensureCapacity(digits); - const uint8 = writer.uint8; - const x = writer.x; - const newX = x + digits; - let i = newX - 1; - while (i >= x) { - const remainder = length % 10; - uint8[i--] = remainder + 48; - length = (length - remainder) / 10; - } - writer.x = newX; - } - - public encodeCmd(args: unknown[]): Uint8Array { - this.writeCmd(args); - return this.writer.flush(); - } - - public writeCmd(args: unknown[]): void { - const length = args.length; - this.writeArrHdr(length); - for (let i = 0; i < length; i++) { - const arg = args[i]; - if (arg instanceof Uint8Array) this.writeBin(arg); - else this.writeBulkStrAscii(arg + ''); - } - } - - public encodeCmdUtf8(args: unknown[]): Uint8Array { - this.writeCmdUtf8(args); - return this.writer.flush(); - } - - public writeCmdUtf8(args: unknown[]): void { - const length = args.length; - this.writeArrHdr(length); - for (let i = 0; i < length; i++) this.writeArgUtf8(args[i]); - } - - public writeArgUtf8(arg: unknown): void { - if (arg instanceof Uint8Array) return this.writeBin(arg); - else this.writeBulkStr(arg + ''); - } - - public writeNull(): void { - this.writer.u8u16( - RESP.NULL, // _ - RESP.RN, // \r\n - ); - } - - public writeNullStr(): void { - this.writer.u8u32( - RESP.STR_BULK, // $ - 45 * 0x1000000 + // - - 49 * 0x10000 + // 1 - RESP.RN, // \r\n - ); - } - - public writeNullArr(): void { - this.writer.u8u32( - RESP.ARR, // * - 45 * 0x1000000 + // - - 49 * 0x10000 + // 1 - RESP.RN, // \r\n - ); - } - - public writeBoolean(bool: boolean): void { - this.writer.u32( - bool - ? RESP.BOOL * 0x1000000 + // # - 116 * 0x10000 + // t - RESP.RN // \r\n - : RESP.BOOL * 0x1000000 + // # - 102 * 0x10000 + // f - RESP.RN, // \r\n - ); - } - - public writeNumber(num: number): void { - if (isSafeInteger(num)) this.writeInteger(num); - else if (typeof num === 'bigint') this.writeBigInt(num); - else this.writeFloat(num); - } - - public writeBigInt(int: bigint): void { - const writer = this.writer; - writer.u8(RESP.BIG); // ( - writer.ascii(int + ''); - writer.u16(RESP.RN); // \r\n - } - - public writeInteger(int: number): void { - const writer = this.writer; - writer.u8(RESP.INT); // : - writer.ascii(int + ''); - writer.u16(RESP.RN); // \r\n - } - - public writeUInteger(uint: number): void { - this.writeInteger(uint); - } - - public writeFloat(float: number): void { - const writer = this.writer; - writer.u8(RESP.FLOAT); // , - switch (float) { - case Infinity: - writer.u8u16( - 105, // i - (110 << 8) | // n - 102, // f - ); - break; - case -Infinity: - writer.u32( - (45 * 0x1000000 + // - - 105 * 0x10000 + // i - (110 << 8)) | // n - 102, // f - ); - break; - default: - if (float !== float) - writer.u8u16( - 110, // n - (97 << 8) | // a - 110, // n - ); - else writer.ascii(float + ''); - break; - } - writer.u16(RESP.RN); // \r\n - } - - public writeBin(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.u8(RESP.STR_BULK); // $ - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - writer.buf(buf, length); - writer.u16(RESP.RN); // \r\n - } - - public writeBinHdr(length: number): void { - throw new Error('Not implemented'); - // Because then we also need `.writeBinBody()` which would emit trailing `\r\n`. - } - - public writeStr(str: string): void { - const length = str.length; - if (length < 64 && !REG_RN.test(str)) this.writeSimpleStr(str); - else this.writeVerbatimStr('txt', str); - } - - public writeStrHdr(length: number): void { - throw new Error('Not implemented'); - // Because then we also need `.writeBinBody()` which would emit trailing `\r\n`. - } - - public writeSimpleStr(str: string): void { - const writer = this.writer; - writer.u8(RESP.STR_SIMPLE); // + - writer.ensureCapacity(str.length << 2); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeSimpleStrAscii(str: string): void { - const writer = this.writer; - writer.u8(RESP.STR_SIMPLE); // + - writer.ascii(str); - writer.u16(RESP.RN); // \r\n - } - - public writeBulkStr(str: string): void { - const writer = this.writer; - const size = utf8Size(str); - writer.u8(RESP.STR_BULK); // $ - this.writeLength(size); - writer.u16(RESP.RN); // \r\n - writer.ensureCapacity(size); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeBulkStrAscii(str: string): void { - const writer = this.writer; - writer.u8(RESP.STR_BULK); // $ - this.writeLength(str.length); - writer.u16(RESP.RN); // \r\n - writer.ascii(str); - writer.u16(RESP.RN); // \r\n - } - - public writeAsciiStr(str: string): void { - const isSimple = !REG_RN.test(str); - if (isSimple) this.writeSimpleStr(str); - else this.writeBulkStrAscii(str); - } - - public writeVerbatimStr(encoding: string, str: string): void { - const writer = this.writer; - const size = utf8Size(str); - writer.u8(RESP.STR_VERBATIM); // = - this.writeLength(size + 4); - writer.u16(RESP.RN); // \r\n - writer.u32( - encoding.charCodeAt(0) * 0x1000000 + // t - (encoding.charCodeAt(1) << 16) + // x - (encoding.charCodeAt(2) << 8) + // t - 58, // : - ); - writer.ensureCapacity(size); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeErr(str: string): void { - if (str.length < 64 && !REG_RN.test(str)) this.writeSimpleErr(str); - else this.writeBulkErr(str); - } - - public writeSimpleErr(str: string): void { - const writer = this.writer; - writer.u8(RESP.ERR_SIMPLE); // - - writer.ensureCapacity(str.length << 2); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeBulkErr(str: string): void { - const writer = this.writer; - const size = utf8Size(str); - writer.u8(RESP.ERR_BULK); // ! - this.writeLength(size); - writer.u16(RESP.RN); // \r\n - writer.ensureCapacity(size); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeArr(arr: unknown[]): void { - const writer = this.writer; - const length = arr.length; - writer.u8(RESP.ARR); // * - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - } - - public writeArrHdr(length: number): void { - const writer = this.writer; - writer.u8(RESP.ARR); // * - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - } - - public writeObj(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - const length = keys.length; - writer.u8(RESP.OBJ); // % - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } - - public writeObjHdr(length: number): void { - const writer = this.writer; - writer.u8(RESP.OBJ); // % - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - } - - public writeAttr(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - const length = keys.length; - writer.u8(RESP.ATTR); // | - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - this.writeAny(obj[key]); - } - } - - public writeSet(set: Set): void { - const writer = this.writer; - const length = set.size; - writer.u8(RESP.SET); // ~ - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) set.forEach((value) => this.writeAny(value)); - } - - public writePush(elements: unknown[]): void { - const writer = this.writer; - const length = elements.length; - writer.u8(RESP.PUSH); // > - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) this.writeAny(elements[i]); - } - - /** - * Called when the encoder encounters a value that it does not know how to encode. - * - * @param value Some JavaScript value. - */ - public writeUnknown(value: unknown): void { - this.writeNull(); - } - - public writeUndef(): void { - this.writeNull(); - } - - protected writeRn(): void { - this.writer.u16(RESP.RN); // \r\n - } - - // ---------------------------------------------------------- Stream encoding - - public writeStartStr(): void { - this.writer.u32( - RESP.STR_BULK * 0x1000000 + // $ - (63 << 16) + // ? - RESP.RN, // \r\n - ); - } - - public writeStrChunk(str: string): void { - const writer = this.writer; - writer.u8(59); // ; - const size = utf8Size(str); - this.writeLength(size); - writer.u16(RESP.RN); // \r\n - writer.ensureCapacity(size); - writer.utf8(str); - writer.u16(RESP.RN); // \r\n - } - - public writeEndStr(): void { - this.writer.u32( - 59 * 0x1000000 + // ; - (48 << 16) + // 0 - RESP.RN, // \r\n - ); - } - - public writeStartBin(): void { - this.writer.u32( - 36 * 0x1000000 + // $ - (63 << 16) + // ? - RESP.RN, // \r\n - ); - } - - public writeBinChunk(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.u8(59); // ; - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - writer.buf(buf, length); - writer.u16(RESP.RN); // \r\n - } - - public writeEndBin(): void { - this.writer.u32( - 59 * 0x1000000 + // ; - (48 << 16) + // 0 - RESP.RN, // \r\n - ); - } - - public writeStartArr(): void { - this.writer.u32( - RESP.ARR * 0x1000000 + // * - (63 << 16) + // ? - RESP.RN, // \r\n - ); - } - - public writeArrChunk(item: unknown): void { - this.writeAny(item); - } - - public writeEndArr(): void { - this.writer.u8u16( - 46, // . - RESP.RN, // \r\n - ); - } - - public writeStartObj(): void { - this.writer.u32( - 37 * 0x1000000 + // % - (63 << 16) + // ? - RESP.RN, // \r\n - ); - } - - public writeObjChunk(key: string, value: unknown): void { - this.writeStr(key); - this.writeAny(value); - } - - public writeEndObj(): void { - this.writer.u8u16( - 46, // . - RESP.RN, // \r\n - ); - } -} diff --git a/src/json-pack/resp/RespEncoderLegacy.ts b/src/json-pack/resp/RespEncoderLegacy.ts deleted file mode 100644 index 81e848dbef..0000000000 --- a/src/json-pack/resp/RespEncoderLegacy.ts +++ /dev/null @@ -1,96 +0,0 @@ -import {RESP} from './constants'; -import {RespAttributes, RespPush, RespVerbatimString} from './extensions'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {RespEncoder} from './RespEncoder'; -import type {IWriter, IWriterGrowable} from '../../util/buffers'; - -const REG_RN = /[\r\n]/; -const isSafeInteger = Number.isSafeInteger; - -/** - * Implements RESP v2 encoding. - */ -export class RespEncoderLegacy extends RespEncoder { - public writeAny(value: unknown): void { - switch (typeof value) { - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'boolean': - return this.writeSimpleStr(value ? 'TRUE' : 'FALSE'); - case 'object': { - if (!value) return this.writeNull(); - if (value instanceof Array) return this.writeArr(value); - if (value instanceof Uint8Array) return this.writeBin(value); - if (value instanceof Error) return this.writeErr(value.message); - if (value instanceof Set) return this.writeSet(value); - if (value instanceof JsonPackExtension) { - if (value instanceof RespPush) return this.writeArr(value.val); - if (value instanceof RespVerbatimString) return this.writeStr(value.val); - if (value instanceof RespAttributes) return this.writeObj(value.val); - } - return this.writeObj(value as Record); - } - case 'undefined': - return this.writeUndef(); - case 'bigint': - return this.writeSimpleStrAscii(value + ''); - default: - return this.writeUnknown(value); - } - } - - public writeNumber(num: number): void { - if (isSafeInteger(num)) this.writeInteger(num); - else this.writeSimpleStrAscii(num + ''); - } - - public writeStr(str: string): void { - const length = str.length; - if (length < 64 && !REG_RN.test(str)) this.writeSimpleStr(str); - else this.writeBulkStr(str); - } - - public writeNull(): void { - this.writeNullArr(); - } - - public writeErr(str: string): void { - if (str.length < 64 && !REG_RN.test(str)) this.writeSimpleErr(str); - else this.writeBulkStr(str); - } - - public writeSet(set: Set): void { - this.writeArr([...set]); - } - - public writeArr(arr: unknown[]): void { - const writer = this.writer; - const length = arr.length; - writer.u8(RESP.ARR); // * - this.writeLength(length); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) { - const val = arr[i]; - if (val === null) this.writeNullStr(); - else this.writeAny(val); - } - } - - public writeObj(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - const length = keys.length; - writer.u8(RESP.ARR); // % - this.writeLength(length << 1); - writer.u16(RESP.RN); // \r\n - for (let i = 0; i < length; i++) { - const key = keys[i]; - this.writeStr(key); - const val = obj[key]; - if (val === null) this.writeNullStr(); - else this.writeAny(val); - } - } -} diff --git a/src/json-pack/resp/RespStreamingDecoder.ts b/src/json-pack/resp/RespStreamingDecoder.ts deleted file mode 100644 index c9116f2dce..0000000000 --- a/src/json-pack/resp/RespStreamingDecoder.ts +++ /dev/null @@ -1,114 +0,0 @@ -import {StreamingReader} from '../../util/buffers/StreamingReader'; -import {RespDecoder} from './RespDecoder'; - -/** - * Streaming decoder for RESP protocol. Can be used to decode data from - * a stream where messages are arbitrary split into chunks. - * - * Example: - * - * ```ts - * const decoder = new RespStreamingDecoder(); - * - * decoder.push(new Uint8Array([43, 49, 13, 10])); - * - * let val; - * while ((val = decoder.read()) !== undefined) { - * console.log(val); - * } - * ``` - */ -export class RespStreamingDecoder { - protected readonly reader = new StreamingReader(); - protected readonly decoder = new RespDecoder(this.reader); - - /** - * When set to true, the decoder will attempt to decode RESP Bulk strings - * (which are binary strings, i.e. Uint8Array) as UTF-8 strings. If the - * string is not valid UTF-8, it will be returned as a Uint8Array. - */ - public get tryUtf8(): boolean { - return this.decoder.tryUtf8; - } - public set tryUtf8(value: boolean) { - this.decoder.tryUtf8 = value; - } - - /** - * Add a chunk of data to be decoded. - * @param uint8 `Uint8Array` chunk of data to be decoded. - */ - public push(uint8: Uint8Array): void { - this.reader.push(uint8); - } - - /** - * Decode one value from the stream. If `undefined` is returned, then - * there is not enough data to decode or the stream is finished. - * - * There could be multiple values in the stream, so this method should be - * called in a loop until `undefined` is returned. - * - * @return Decoded value or `undefined` if there is not enough data to decode. - */ - public read(): unknown | undefined { - const reader = this.reader; - if (reader.size() === 0) return undefined; - const x = reader.x; - try { - const val = this.decoder.val(); - reader.consume(); - return val; - } catch (error) { - if (error instanceof RangeError) { - reader.x = x; - return undefined; - } else throw error; - } - } - - /** - * Decode only one RESP command from the stream, if the value is not a - * command, an error will be thrown. - * - * @returns Redis command and its arguments or `undefined` if there is - * not enough data to decode. - */ - public readCmd(): [cmd: string, ...args: Uint8Array[]] | undefined { - const reader = this.reader; - if (reader.size() === 0) return undefined; - const x = reader.x; - try { - const args = this.decoder.readCmd(); - reader.consume(); - return args; - } catch (error) { - if (error instanceof RangeError) { - reader.x = x; - return undefined; - } else throw error; - } - } - - /** - * Skips one value from the stream. If `undefined` is returned, then - * there is not enough data to skip or the stream is finished. - * @returns `null` if a value was skipped, `undefined` if there is not - * enough data to skip. - */ - public skip(): null | undefined { - const reader = this.reader; - if (reader.size() === 0) return undefined; - const x = reader.x; - try { - this.decoder.skipAny(); - reader.consume(); - return null; - } catch (error) { - if (error instanceof RangeError) { - reader.x = x; - return undefined; - } else throw error; - } - } -} diff --git a/src/json-pack/resp/__tests__/RespDecoder.spec.ts b/src/json-pack/resp/__tests__/RespDecoder.spec.ts deleted file mode 100644 index ab192c83b8..0000000000 --- a/src/json-pack/resp/__tests__/RespDecoder.spec.ts +++ /dev/null @@ -1,235 +0,0 @@ -import {RespEncoder} from '../RespEncoder'; -import {RespDecoder} from '../RespDecoder'; -import {bufferToUint8Array} from '../../../util/buffers/bufferToUint8Array'; -import {RespAttributes, RespPush} from '../extensions'; -import {Writer} from '../../../util/buffers/Writer'; -import {utf8} from '../../../util/buffers/strings'; - -const decode = (encoded: string | Uint8Array): unknown => { - const decoder = new RespDecoder(); - const buf = typeof encoded === 'string' ? bufferToUint8Array(Buffer.from(encoded)) : encoded; - const decoded = decoder.read(buf); - return decoded; -}; - -const encoder = new RespEncoder(new Writer(4)); -const assertCodec = (value: unknown, expected: unknown = value): void => { - const encoded = encoder.encode(value); - // console.log(Buffer.from(encoded).toString()); - const decoded = decode(encoded); - expect(decoded).toStrictEqual(expected); - const encoded2 = encoder.encode(value); - const decoded2 = decode(encoded2); - expect(decoded2).toStrictEqual(expected); -}; - -describe('nulls', () => { - test('null', () => { - assertCodec(null); - }); -}); - -describe('booleans', () => { - test('true', () => { - assertCodec(true); - }); - - test('false', () => { - assertCodec(false); - }); -}); - -describe('integers', () => { - test('zero', () => assertCodec(0)); - test('positive', () => assertCodec(123)); - test('negative', () => assertCodec(-2348934)); - test('positive with leading "+"', () => { - const decoded = decode(':+123\r\n'); - expect(decoded).toBe(123); - }); -}); - -describe('big ints', () => { - test('zero', () => assertCodec(BigInt('0'))); - test('positive', () => assertCodec(BigInt('123'))); - test('negative', () => assertCodec(BigInt('-2348934'))); - test('positive with leading "+"', () => { - const decoded = decode('(+123\r\n'); - expect(decoded).toEqual(BigInt('123')); - }); -}); - -describe('floats', () => { - test('positive', () => assertCodec([1.123])); - test('negative', () => assertCodec([-43.234435])); - test('negative', () => assertCodec([-5445e-10])); - test('negative', () => assertCodec([-5445e-20])); - test('negative', () => assertCodec([-5445e-30])); - test('inf', () => assertCodec([Infinity])); - test('-inf', () => assertCodec([-Infinity])); - test('nan', () => assertCodec([NaN])); - - test('decodes ",inf"', () => { - const decoded = decode(',inf\r\n'); - expect(decoded).toEqual(Infinity); - }); - - test('decodes ",-inf"', () => { - const decoded = decode(',-inf\r\n'); - expect(decoded).toEqual(-Infinity); - }); - - test('decodes ",nan"', () => { - const decoded = decode(',nan\r\n'); - expect(decoded).toEqual(NaN); - }); -}); - -const stringCases: [string, string][] = [ - ['empty string', ''], - ['short string', 'foo bar'], - ['short string with emoji', 'foo bar🍼'], - ['short string with emoji and newline', 'foo bar\n🍼'], - ['simple string with newline', 'foo\nbar'], -]; - -describe('strings', () => { - for (const [name, value] of stringCases) { - test(name, () => assertCodec(value)); - } - - describe('verbatim strings', () => { - test('example from docs', () => { - const encoded = '=15\r\ntxt:Some string\r\n'; - const decoded = decode(encoded); - expect(decoded).toBe('Some string'); - }); - }); -}); - -describe('binary', () => { - test('empty blob', () => assertCodec(new Uint8Array(0))); - test('small blob', () => assertCodec(new Uint8Array([1, 2, 3]))); - test('blob with new lines', () => assertCodec(new Uint8Array([1, 2, 3, 10, 13, 14, 64, 65]))); -}); - -describe('errors', () => { - for (const [name, value] of stringCases) { - test(name, () => assertCodec(new Error(value))); - } -}); - -const arrays: [string, unknown[]][] = [ - ['empty array', []], - ['simple array', [1, 2, 3]], - ['with strings', ['foo', 'bar']], - ['nested', [[]]], - ['surrounded by special strings', ['a\n', 'b😱', [0, -1, 1], '\nasdf\r\n\r💪\nadsf']], -]; - -describe('arrays', () => { - for (const [name, value] of arrays) test(name, () => assertCodec(value)); -}); - -describe('sets', () => { - for (const [name, value] of arrays) test(name, () => assertCodec(new Set(value))); -}); - -describe('pushes', () => { - for (const [name, value] of arrays) test(name, () => assertCodec(new RespPush(value))); -}); - -const maps: [string, Record][] = [ - ['empty map', {}], - ['simple map', {foo: 'bar'}], - ['multiple keys', {foo: 'bar', baz: 'qux'}], - ['nested', {foo: {bar: 'baz'}}], - ['surrounded by special strings', {foo: 'bar', baz: 'qux', quux: ['a\n', 'b😱', [0, -1, 1], '\nasdf\r\n\r💪\nadsf']}], - ['fuzzer 1', {a: 'b', 'a*|Avi5:7%7El': false}], - [ - 'fuzzer 2', - { - 'u.qSvG-7#j0tp1Z': [ - 'Mk9|s2<[-$k2sEq', - '.YyA', - ',g:V5el?o1', - ['/-=gfBa7@r'], - null, - 'x0"', - 899663861.7189225, - ['-yM}#tH>Z|0', '?x4c-M', 'V`Wjk', 962664739.7776917, 541764469.8786258], - 39815384.70374191, - '%J,TE6', - 867117612.5557965, - 432039764.7694767, - {'&3qo`uOc@]7c': -1199425724646684, '(3': 98978664.1896191}, - 941209461.4820778, - 444029027.33100927, - ], - ':xwsOx[u0:\\,': 116172902.03305908, - '=Em$Bo+t4': 118717435.20500576, - 'D3 hvV+uBsY^0': ' Mr!`Pjno;ME_', - 'l\\Wv1bs': null, - F: 175071663.912447, - 's-o}fQO2e': null, - 'K!q]': 'LBm,GEw,`BpQxIq', - "(:'-g`;x": 'r\\?K;AZWT1S:w0_-', - }, - ], -]; - -describe('objects', () => { - for (const [name, value] of maps) test(name, () => assertCodec(value)); - - describe('when .tryUtf8 = true', () => { - test('parses bulk strings as UTF8 strings', () => { - const encoded = '%1\r\n$3\r\nfoo\r\n$3\r\nbar\r\n'; - const decoder = new RespDecoder(); - decoder.tryUtf8 = true; - const decoded = decoder.read(Buffer.from(encoded)); - expect(decoded).toStrictEqual({foo: 'bar'}); - }); - - test('parses invalid UTF8 as Uint8Array', () => { - const encoded = encoder.encode({foo: new Uint8Array([0xc3, 0x28])}); - const decoder = new RespDecoder(); - decoder.tryUtf8 = true; - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual({foo: new Uint8Array([0xc3, 0x28])}); - }); - }); -}); - -describe('attributes', () => { - for (const [name, value] of maps) test(name, () => assertCodec(new RespAttributes(value))); -}); - -describe('nulls', () => { - test('can decode string null', () => { - const decoded = decode('$-1\r\n'); - expect(decoded).toBe(null); - }); - - test('can decode array null', () => { - const decoded = decode('*-1\r\n'); - expect(decoded).toBe(null); - }); -}); - -describe('commands', () => { - test('can decode a PING command', () => { - const encoded = encoder.encodeCmd(['PING']); - const decoder = new RespDecoder(); - decoder.reader.reset(encoded); - const decoded = decoder.readCmd(); - expect(decoded).toEqual(['PING']); - }); - - test('can decode a SET command', () => { - const encoded = encoder.encodeCmd(['SET', 'foo', 'bar']); - const decoder = new RespDecoder(); - decoder.reader.reset(encoded); - const decoded = decoder.readCmd(); - expect(decoded).toEqual(['SET', utf8`foo`, utf8`bar`]); - }); -}); diff --git a/src/json-pack/resp/__tests__/RespEncoder.spec.ts b/src/json-pack/resp/__tests__/RespEncoder.spec.ts deleted file mode 100644 index 9a1b1b306c..0000000000 --- a/src/json-pack/resp/__tests__/RespEncoder.spec.ts +++ /dev/null @@ -1,355 +0,0 @@ -import {bufferToUint8Array} from '../../../util/buffers/bufferToUint8Array'; -import {RespEncoder} from '../RespEncoder'; -import {RespVerbatimString} from '../extensions'; -const Parser = require('redis-parser'); - -const parse = (uint8: Uint8Array): unknown => { - let result: unknown; - const parser = new Parser({ - returnReply(reply: any, b: any, c: any) { - result = reply; - }, - returnError(err: any) { - result = err; - }, - returnFatalError(err: any) { - result = err; - }, - returnBuffers: false, - stringNumbers: false, - }); - parser.execute(Buffer.from(uint8)); - return result; -}; - -const toStr = (uint8: Uint8Array): string => { - return Buffer.from(uint8).toString(); -}; - -describe('strings', () => { - describe('.writeSimpleStr()', () => { - test('empty string', () => { - const encoder = new RespEncoder(); - encoder.writeSimpleStr(''); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('+\r\n'); - expect(parse(encoded)).toBe(''); - }); - - test('short string', () => { - const encoder = new RespEncoder(); - encoder.writeSimpleStr('abc!'); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('+abc!\r\n'); - expect(parse(encoded)).toBe('abc!'); - }); - }); - - describe('.writeBulkStr()', () => { - test('empty string', () => { - const encoder = new RespEncoder(); - encoder.writeBulkStr(''); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('$0\r\n\r\n'); - expect(parse(encoded)).toBe(''); - }); - - test('short string', () => { - const encoder = new RespEncoder(); - encoder.writeBulkStr('abc!'); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('$4\r\nabc!\r\n'); - expect(parse(encoded)).toBe('abc!'); - }); - }); - - describe('.writeVerbatimStr()', () => { - test('empty string', () => { - const encoder = new RespEncoder(); - encoder.writeVerbatimStr('txt', ''); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('=4\r\ntxt:\r\n'); - }); - - test('short string', () => { - const encoder = new RespEncoder(); - encoder.writeVerbatimStr('txt', 'asdf'); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('=8\r\ntxt:asdf\r\n'); - }); - - test('can encode verbatim string using RespVerbatimString', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new RespVerbatimString('asdf')); - expect(toStr(encoded)).toBe('=8\r\ntxt:asdf\r\n'); - }); - }); -}); - -describe('binary', () => { - test('empty blob', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Uint8Array(0)); - expect(toStr(encoded)).toBe('$0\r\n\r\n'); - expect(parse(encoded)).toBe(''); - }); - - test('small blob', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Uint8Array([65, 66])); - expect(toStr(encoded)).toBe('$2\r\nAB\r\n'); - expect(parse(encoded)).toBe('AB'); - }); -}); - -describe('.writeAsciiString()', () => { - test('can write "OK"', () => { - const encoder = new RespEncoder(); - encoder.writeAsciiStr('OK'); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('+OK\r\n'); - expect(parse(encoded)).toBe('OK'); - }); -}); - -describe('errors', () => { - test('can encode simple error', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Error('ERR')); - expect(toStr(encoded)).toBe('-ERR\r\n'); - expect(parse(encoded)).toBeInstanceOf(Error); - expect((parse(encoded) as any).message).toBe('ERR'); - }); - - test('can encode bulk error', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Error('a\nb')); - expect(toStr(encoded)).toBe('!3\r\na\nb\r\n'); - expect(parse(encoded)).toBeInstanceOf(Error); - }); -}); - -describe('integers', () => { - test('zero', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(0); - expect(toStr(encoded)).toBe(':0\r\n'); - expect(parse(encoded)).toBe(0); - }); - - test('positive integer', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(23423432543); - expect(toStr(encoded)).toBe(':23423432543\r\n'); - expect(parse(encoded)).toBe(23423432543); - }); - - test('negative integer', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(-11111111); - expect(toStr(encoded)).toBe(':-11111111\r\n'); - expect(parse(encoded)).toBe(-11111111); - }); -}); - -describe('arrays', () => { - test('empty array', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode([]); - expect(toStr(encoded)).toBe('*0\r\n'); - expect(parse(encoded)).toEqual([]); - }); - - test('array of numbers', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode([1, 2, 3]); - expect(toStr(encoded)).toBe('*3\r\n:1\r\n:2\r\n:3\r\n'); - expect(parse(encoded)).toEqual([1, 2, 3]); - }); - - test('array of strings and numbers', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode([1, 'abc', 3]); - expect(toStr(encoded)).toBe('*3\r\n:1\r\n+abc\r\n:3\r\n'); - expect(parse(encoded)).toEqual([1, 'abc', 3]); - }); -}); - -describe('nulls', () => { - test('a single null', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(null); - expect(toStr(encoded)).toBe('_\r\n'); - }); - - test('null in array', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode([1, 2, null]); - expect(toStr(encoded)).toBe('*3\r\n:1\r\n:2\r\n_\r\n'); - }); - - test('string null', () => { - const encoder = new RespEncoder(); - encoder.writeNullStr(); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('$-1\r\n'); - expect(parse(encoded)).toEqual(null); - }); - - test('array null', () => { - const encoder = new RespEncoder(); - encoder.writeNullArr(); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('*-1\r\n'); - expect(parse(encoded)).toEqual(null); - }); -}); - -describe('booleans', () => { - test('true', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(true); - expect(toStr(encoded)).toBe('#t\r\n'); - }); - - test('false', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(false); - expect(toStr(encoded)).toBe('#f\r\n'); - }); -}); - -describe('doubles', () => { - test('1.2', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(1.2); - expect(toStr(encoded)).toBe(',1.2\r\n'); - }); -}); - -describe('big numbers', () => { - test('12345678901234567890', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(BigInt('12345678901234567890')); - expect(toStr(encoded)).toBe('(12345678901234567890\r\n'); - }); -}); - -describe('objects', () => { - test('empty object', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode({}); - expect(toStr(encoded)).toBe('%0\r\n'); - }); - - test('simple object', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode({foo: 123}); - expect(toStr(encoded)).toBe('%1\r\n+foo\r\n:123\r\n'); - }); -}); - -describe('attributes', () => { - test('empty attributes', () => { - const encoder = new RespEncoder(); - encoder.writeAttr({}); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('|0\r\n'); - }); - - test('simple object', () => { - const encoder = new RespEncoder(); - encoder.writeAttr({foo: 123}); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('|1\r\n+foo\r\n:123\r\n'); - }); -}); - -describe('sets', () => { - test('empty set', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Set()); - expect(toStr(encoded)).toBe('~0\r\n'); - }); - - test('array of numbers', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encode(new Set([1])); - expect(toStr(encoded)).toBe('~1\r\n:1\r\n'); - }); -}); - -describe('pushes', () => { - test('empty push', () => { - const encoder = new RespEncoder(); - encoder.writePush([]); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('>0\r\n'); - }); - - test('two elements', () => { - const encoder = new RespEncoder(); - encoder.writePush([1, 32]); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('>2\r\n:1\r\n:32\r\n'); - }); -}); - -describe('streaming data', () => { - describe('strings', () => { - test('can write a streaming string', () => { - const encoder = new RespEncoder(); - encoder.writeStartStr(); - encoder.writeStrChunk('abc'); - encoder.writeStrChunk('def'); - encoder.writeEndStr(); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('$?\r\n;3\r\nabc\r\n;3\r\ndef\r\n;0\r\n'); - }); - }); - - describe('binary', () => { - test('can write a streaming binary', () => { - const encoder = new RespEncoder(); - encoder.writeStartBin(); - encoder.writeBinChunk(new Uint8Array([65])); - encoder.writeBinChunk(new Uint8Array([66])); - encoder.writeEndBin(); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('$?\r\n;1\r\nA\r\n;1\r\nB\r\n;0\r\n'); - }); - }); -}); - -describe('commands', () => { - describe('.writeCmd()', () => { - test('can encode a simple command', () => { - const encoder = new RespEncoder(); - encoder.writeCmd(['SET', 'foo', 'bar']); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n'); - }); - - test('casts numbers to strings', () => { - const encoder = new RespEncoder(); - encoder.writeCmd(['SET', 'foo', 123]); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n'); - }); - - test('can encode Uint8Array', () => { - const encoder = new RespEncoder(); - const encoded = encoder.encodeCmd([bufferToUint8Array(Buffer.from('SET')), 'foo', 123]); - expect(toStr(encoded)).toBe('*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\n123\r\n'); - }); - }); - - describe('.can encode emojis()', () => { - test('can encode a simple command', () => { - const encoder = new RespEncoder(); - encoder.writeCmdUtf8(['SET', 'foo 👍', 'bar']); - const encoded = encoder.writer.flush(); - expect(toStr(encoded)).toBe('*3\r\n$3\r\nSET\r\n$8\r\nfoo 👍\r\n$3\r\nbar\r\n'); - }); - }); -}); diff --git a/src/json-pack/resp/__tests__/RespEncoderLegacy.spec.ts b/src/json-pack/resp/__tests__/RespEncoderLegacy.spec.ts deleted file mode 100644 index a7d67763e2..0000000000 --- a/src/json-pack/resp/__tests__/RespEncoderLegacy.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {RespEncoderLegacy} from '../RespEncoderLegacy'; - -const encode = (value: unknown): string => { - const encoder = new RespEncoderLegacy(); - const encoded = encoder.encode(value); - return Buffer.from(encoded).toString(); -}; - -test('can encode simple strings', () => { - expect(encode('')).toBe('+\r\n'); - expect(encode('asdf')).toBe('+asdf\r\n'); -}); - -test('can encode simple errors', () => { - expect(encode(new Error('asdf'))).toBe('-asdf\r\n'); -}); - -test('can encode integers', () => { - expect(encode(0)).toBe(':0\r\n'); - expect(encode(123)).toBe(':123\r\n'); - expect(encode(-422469777)).toBe(':-422469777\r\n'); -}); - -test('can encode bulk strings', () => { - expect(encode('ab\nc')).toBe('$4\r\nab\nc\r\n'); - expect(encode(new Uint8Array([65]))).toBe('$1\r\nA\r\n'); -}); - -test('can encode arrays', () => { - expect(encode(['a', 1])).toBe('*2\r\n+a\r\n:1\r\n'); -}); - -test('encodes null as nullable array', () => { - expect(encode(null)).toBe('*-1\r\n'); -}); - -test('encodes null in nested structure as nullable string', () => { - expect(encode(['a', 'b', null])).toBe('*3\r\n+a\r\n+b\r\n$-1\r\n'); -}); - -test('encodes booleans as strings', () => { - expect(encode(true)).toBe('+TRUE\r\n'); - expect(encode(false)).toBe('+FALSE\r\n'); -}); - -test('encodes floats as strings', () => { - expect(encode(1.23)).toBe('+1.23\r\n'); -}); - -test('encodes objects as 2-tuple arrays', () => { - expect(encode({foo: 'bar'})).toBe('*2\r\n+foo\r\n+bar\r\n'); -}); diff --git a/src/json-pack/resp/__tests__/RespStreamingDecoder.spec.ts b/src/json-pack/resp/__tests__/RespStreamingDecoder.spec.ts deleted file mode 100644 index 112fd3a054..0000000000 --- a/src/json-pack/resp/__tests__/RespStreamingDecoder.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import {RespStreamingDecoder} from '../RespStreamingDecoder'; -import {RespEncoder} from '../RespEncoder'; -import {concatList} from '../../../util/buffers/concat'; -import {documents} from '../../../__tests__/json-documents'; -import {utf8} from '../../../util/buffers/strings'; - -const encoder = new RespEncoder(); - -test('can decode simple string', () => { - const decoder = new RespStreamingDecoder(); - const encoded = encoder.encode('abc'); - expect(decoder.read()).toBe(undefined); - decoder.push(encoded); - expect(decoder.read()).toBe('abc'); - expect(decoder.read()).toBe(undefined); - expect(decoder.read()).toBe(undefined); -}); - -test('can stream one byte at a time', () => { - const decoder = new RespStreamingDecoder(); - const docs = [ - 1, - 123.1234, - -3, - true, - null, - false, - Infinity, - NaN, - -Infinity, - '', - 'abc', - 'a\nb', - 'a\rb', - 'emoji: 🐶', - '😀', - '😀😀', - '😀😀😀', - new Error('123'), - new Error('\n'), - null, - {}, - [{foo: -43, bar: 'a\nb'}], - ]; - const encoded = docs.map((doc) => encoder.encode(doc)); - const decoded: unknown[] = []; - const bufs = concatList(encoded); - for (let i = 0; i < bufs.length; i++) { - decoder.push(new Uint8Array([bufs[i]])); - const read = decoder.read(); - if (read !== undefined) decoded.push(read); - } - expect(decoded).toEqual(docs); -}); - -test('can stream 49 bytes at a time', () => { - const decoder = new RespStreamingDecoder(); - const docs = documents; - const encoded = docs.map((doc) => encoder.encode(doc)); - const decoded: unknown[] = []; - const bufs = concatList(encoded); - for (let i = 0; i < bufs.length; i += 49) { - const max = Math.min(bufs.length, i + 49); - decoder.push(new Uint8Array(bufs.slice(i, max))); - let read: any; - while ((read = decoder.read()) !== undefined) decoded.push(read); - } - expect(decoded).toEqual(docs); -}); - -test('can decode a command', () => { - const encoded = encoder.encodeCmd(['SET', 'foo', 'bar']); - const decoder = new RespStreamingDecoder(); - decoder.push(encoded); - const decoded = decoder.readCmd(); - expect(decoded).toEqual(['SET', utf8`foo`, utf8`bar`]); -}); diff --git a/src/json-pack/resp/__tests__/codec.spec.ts b/src/json-pack/resp/__tests__/codec.spec.ts deleted file mode 100644 index 7ed84fb5d5..0000000000 --- a/src/json-pack/resp/__tests__/codec.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {RespEncoder} from '../RespEncoder'; -import {RespDecoder} from '../RespDecoder'; -import {documents} from '../../../__tests__/json-documents'; -import {binaryDocuments} from '../../../__tests__/binary-documents'; - -const run = (encoder: RespEncoder, decoder: RespDecoder) => { - describe('JSON documents', () => { - for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - const encoded = encoder.encode(t.json); - const decoded = decoder.read(encoded); - expect(decoded).toEqual(t.json); - }); - } - }); -}; - -const runBinary = (encoder: RespEncoder, decoder: RespDecoder) => { - describe('binary documents', () => { - for (const t of binaryDocuments) { - (t.only ? test.only : test)(t.name, () => { - const encoded = encoder.encode(t.json); - const decoded = decoder.read(encoded); - expect(decoded).toEqual(t.json); - }); - } - }); -}; - -describe('dedicated codecs', () => { - const encoder = new RespEncoder(); - const decoder = new RespDecoder(); - run(encoder, decoder); - runBinary(encoder, decoder); -}); - -const encoder = new RespEncoder(); -const decoder = new RespDecoder(); - -describe('shared codecs', () => { - run(encoder, decoder); - runBinary(encoder, decoder); -}); diff --git a/src/json-pack/resp/__tests__/fuzzing.spec.ts b/src/json-pack/resp/__tests__/fuzzing.spec.ts deleted file mode 100644 index 548d396ae5..0000000000 --- a/src/json-pack/resp/__tests__/fuzzing.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {RandomJson} from '../../../json-random'; -import {RespEncoder} from '../RespEncoder'; -import {RespDecoder} from '../RespDecoder'; - -const encoder = new RespEncoder(); -const decoder = new RespDecoder(); - -describe('fuzzing', () => { - test('CborEncoderFast', () => { - for (let i = 0; i < 2000; i++) { - const value = JSON.parse(JSON.stringify(RandomJson.generate())); - const encoded = encoder.encode(value); - const decoded = decoder.read(encoded); - expect(decoded).toStrictEqual(value); - } - }); -}); diff --git a/src/json-pack/resp/__tests__/skipping.spec.ts b/src/json-pack/resp/__tests__/skipping.spec.ts deleted file mode 100644 index da040c0b8a..0000000000 --- a/src/json-pack/resp/__tests__/skipping.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {RespEncoder} from '../RespEncoder'; -import {RespDecoder} from '../RespDecoder'; -import {RespStreamingDecoder} from '../RespStreamingDecoder'; -import {documents} from '../../../__tests__/json-documents'; -import {binaryDocuments} from '../../../__tests__/binary-documents'; - -const docs = [...documents, ...binaryDocuments]; - -const encoder = new RespEncoder(); -const decoder = new RespDecoder(); -const streamingDecoder = new RespStreamingDecoder(); - -describe('skipping', () => { - describe('RespDecoder', () => { - for (const t of docs) { - (t.only ? test.only : test)(t.name, () => { - encoder.writeAny(t.json); - encoder.writeAny({foo: 'bar'}); - const encoded = encoder.writer.flush(); - decoder.reader.reset(encoded); - decoder.skipAny(); - const decoded = decoder.val(); - expect(decoded).toEqual({foo: 'bar'}); - }); - } - }); - - describe('RespStreamingDecoder', () => { - for (const t of docs) { - (t.only ? test.only : test)(t.name, () => { - encoder.writeAny(t.json); - encoder.writeAny({foo: 'bar'}); - const encoded = encoder.writer.flush(); - streamingDecoder.push(encoded); - streamingDecoder.skip(); - const decoded = streamingDecoder.read(); - expect(decoded).toEqual({foo: 'bar'}); - }); - } - }); -}); diff --git a/src/json-pack/resp/constants.ts b/src/json-pack/resp/constants.ts deleted file mode 100644 index c00eb24274..0000000000 --- a/src/json-pack/resp/constants.ts +++ /dev/null @@ -1,27 +0,0 @@ -export const enum RESP { - // Human readable separators - R = 0x0d, // \r - N = 0x0a, // \n - RN = 0x0d0a, // \r\n - - // Data types - NULL = 95, // _ - BOOL = 35, // # - INT = 58, // : - BIG = 40, // ( - FLOAT = 44, // , - STR_SIMPLE = 43, // + - STR_BULK = 36, // $ - STR_VERBATIM = 61, // = - ERR_SIMPLE = 45, // - - ERR_BULK = 33, // ! - ARR = 42, // * - SET = 126, // ~ - OBJ = 37, // % - PUSH = 62, // > - ATTR = 124, // | - - // Special chars - PLUS = 43, // + - MINUS = 45, // - -} diff --git a/src/json-pack/resp/extensions.ts b/src/json-pack/resp/extensions.ts deleted file mode 100644 index c179e4e359..0000000000 --- a/src/json-pack/resp/extensions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {JsonPackExtension} from '../JsonPackExtension'; - -export class RespPush extends JsonPackExtension { - constructor(public readonly val: unknown[]) { - super(1, val); - } -} - -export class RespAttributes extends JsonPackExtension> { - constructor(public readonly val: Record) { - super(2, val); - } -} - -export class RespVerbatimString extends JsonPackExtension { - constructor(public readonly val: string) { - super(3, val); - } -} diff --git a/src/json-pack/resp/index.ts b/src/json-pack/resp/index.ts deleted file mode 100644 index 82c1e20632..0000000000 --- a/src/json-pack/resp/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './constants'; -export * from './extensions'; -export * from './RespEncoder'; -export * from './RespEncoderLegacy'; -export * from './RespDecoder'; -export * from './RespStreamingDecoder'; diff --git a/src/json-pack/types.ts b/src/json-pack/types.ts deleted file mode 100644 index 150ad9340b..0000000000 --- a/src/json-pack/types.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type {IReader, IReaderResettable, IWriter, IWriterGrowable} from '../util/buffers'; -import type {JsonPackExtension} from './JsonPackExtension'; -import type {JsonPackValue} from './JsonPackValue'; - -export type JsonPrimitive = string | number | bigint | boolean | null; -export type JsonValue = JsonPrimitive | JsonArray | JsonObject; -type JsonArray = JsonValue[] | readonly JsonValue[]; -type JsonObject = {[key: string]: JsonValue} | Readonly<{[key: string]: JsonValue}>; - -export type TypedJsonValue = T & JsonValue; - -export type PackPrimitive = JsonPrimitive | undefined | Uint8Array | JsonPackValue | JsonPackExtension | bigint; -export type PackValue = PackPrimitive | PackArray | PackObject; -type PackArray = PackValue[] | readonly PackValue[]; -type PackObject = {[key: string]: PackValue} | Readonly<{[key: string]: PackValue}>; - -export interface BinaryJsonEncoder { - encode(value: unknown): Uint8Array; - writer: IWriter & IWriterGrowable; - writeAny(value: unknown): void; - writeNull(): void; - writeBoolean(bool: boolean): void; - writeNumber(num: number): void; - writeInteger(int: number): void; - writeUInteger(uint: number): void; - writeFloat(float: number): void; - writeBin(buf: Uint8Array): void; - writeAsciiStr(str: string): void; - writeStr(str: string): void; - writeArr(arr: unknown[]): void; - writeObj(obj: Record): void; -} - -export interface StreamingBinaryJsonEncoder { - writeStartStr(): void; - writeStrChunk(str: string): void; - writeEndStr(): void; - writeStartBin(): void; - writeBinChunk(buf: Uint8Array): void; - writeEndBin(): void; - writeStartArr(): void; - writeArrChunk(item: unknown): void; - writeEndArr(): void; - writeStartObj(): void; - writeObjChunk(key: string, value: unknown): void; - writeEndObj(): void; -} - -export interface TlvBinaryJsonEncoder { - writeBinHdr(length: number): void; - writeArrHdr(length: number): void; - writeObjHdr(length: number): void; -} - -export interface BinaryJsonDecoder { - decode(uint8: Uint8Array): unknown; - reader: IReader & IReaderResettable; - read(uint8: Uint8Array): unknown; -} diff --git a/src/json-pack/ubjson/README.md b/src/json-pack/ubjson/README.md deleted file mode 100644 index 4d305e52cc..0000000000 --- a/src/json-pack/ubjson/README.md +++ /dev/null @@ -1,184 +0,0 @@ -## Limitations of the UBJSON format - -- Does not have a native "binary" type representation. Instead, octets are - encoded as a typed arrays of fixed length. Such encoding is reserved for - JavaScript Typed arrays. The `Uint8Array` array is encoded as fixed length - fixed type array of type `U`. -- UBJSON requires big-endian encoding of binary data, however, JavaScript - Typed arrays are always little-endian, because Intel and ARM CPUs are - little-endian. This means that the binary data must be converted to big-endian - before encoding and after decoding. To avoid this transcoding performance - penalty, only `Uint8Array` type is supported. - - -## Benchmarks - -`json-joy` implementation of UBJSON is about an order of magnitude faster than `@shelacek/ubjson`. - -### Encoding - -Node v20: - -``` -npx ts-node benchmarks/json-pack/bench.encoding.ubjson.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v20.1.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Small object, 44 bytes -🤞 json-joy/json-pack UbjsonEncoder x 6,086,774 ops/sec ±0.49% (99 runs sampled) -🤞 @shelacek/ubjson x 249,763 ops/sec ±0.90% (91 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 2,247,813 ops/sec ±0.09% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -🤞 json-joy/json-pack UbjsonEncoder x 467,602 ops/sec ±0.43% (100 runs sampled) -🤞 @shelacek/ubjson x 21,679 ops/sec ±0.63% (93 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 205,665 ops/sec ±0.07% (101 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -🤞 json-joy/json-pack UbjsonEncoder x 139,415 ops/sec ±0.09% (98 runs sampled) -🤞 @shelacek/ubjson x 6,835 ops/sec ±0.75% (80 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 63,793 ops/sec ±0.07% (101 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------- Very large object, 45750 bytes -🤞 json-joy/json-pack UbjsonEncoder x 6,328 ops/sec ±0.13% (99 runs sampled) -🤞 @shelacek/ubjson x 445 ops/sec ±0.43% (77 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 7,131 ops/sec ±0.44% (99 runs sampled) -Fastest is 🤞 Buffer.from(JSON.stringify()) ------------------------------------------------------------------- Object with many keys, 969 bytes -🤞 json-joy/json-pack UbjsonEncoder x 291,303 ops/sec ±0.78% (99 runs sampled) -🤞 @shelacek/ubjson x 15,442 ops/sec ±1.08% (86 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 183,711 ops/sec ±0.82% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -------------------------------------------------------------------------- String ladder, 3398 bytes -🤞 json-joy/json-pack UbjsonEncoder x 272,762 ops/sec ±0.56% (93 runs sampled) -🤞 @shelacek/ubjson x 27,051 ops/sec ±1.11% (87 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 145,414 ops/sec ±0.50% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Long strings, 7011 bytes -🤞 json-joy/json-pack UbjsonEncoder x 424,816 ops/sec ±0.74% (99 runs sampled) -🤞 @shelacek/ubjson x 90,009 ops/sec ±0.69% (93 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 28,931 ops/sec ±0.08% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -🤞 json-joy/json-pack UbjsonEncoder x 2,147,028 ops/sec ±0.23% (99 runs sampled) -🤞 @shelacek/ubjson x 63,720 ops/sec ±0.82% (92 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,015,356 ops/sec ±0.12% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------------- Numbers, 136 bytes -🤞 json-joy/json-pack UbjsonEncoder x 3,039,077 ops/sec ±0.15% (98 runs sampled) -🤞 @shelacek/ubjson x 381,464 ops/sec ±0.16% (97 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,197,582 ops/sec ±0.11% (102 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder ---------------------------------------------------------------------------------- Tokens, 308 bytes -🤞 json-joy/json-pack UbjsonEncoder x 1,661,503 ops/sec ±0.19% (101 runs sampled) -🤞 @shelacek/ubjson x 272,256 ops/sec ±0.11% (101 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,075,468 ops/sec ±0.18% (101 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -``` - -Node v18: - -``` -npx ts-node benchmarks/json-pack/bench.encoding.ubjson.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 ----------------------------------------------------------------------------- Small object, 44 bytes -🤞 json-joy/json-pack UbjsonEncoder x 6,702,065 ops/sec ±1.34% (99 runs sampled) -🤞 @shelacek/ubjson x 244,890 ops/sec ±0.83% (88 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 2,272,407 ops/sec ±0.20% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -------------------------------------------------------------------------- Typical object, 993 bytes -🤞 json-joy/json-pack UbjsonEncoder x 499,534 ops/sec ±0.37% (101 runs sampled) -🤞 @shelacek/ubjson x 21,968 ops/sec ±0.55% (95 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 198,487 ops/sec ±5.53% (90 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Large object, 3741 bytes -🤞 json-joy/json-pack UbjsonEncoder x 101,614 ops/sec ±6.22% (71 runs sampled) -🤞 @shelacek/ubjson x 6,928 ops/sec ±4.39% (86 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 63,549 ops/sec ±2.57% (95 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------- Very large object, 45750 bytes -🤞 json-joy/json-pack UbjsonEncoder x 6,548 ops/sec ±0.26% (99 runs sampled) -🤞 @shelacek/ubjson x 441 ops/sec ±1.05% (80 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 5,973 ops/sec ±1.06% (97 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder ------------------------------------------------------------------- Object with many keys, 969 bytes -🤞 json-joy/json-pack UbjsonEncoder x 299,428 ops/sec ±1.96% (95 runs sampled) -🤞 @shelacek/ubjson x 15,818 ops/sec ±1.29% (86 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 188,231 ops/sec ±0.82% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -------------------------------------------------------------------------- String ladder, 3398 bytes -🤞 json-joy/json-pack UbjsonEncoder x 303,012 ops/sec ±2.13% (97 runs sampled) -🤞 @shelacek/ubjson x 28,397 ops/sec ±1.71% (86 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 126,743 ops/sec ±1.43% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Long strings, 7011 bytes -🤞 json-joy/json-pack UbjsonEncoder x 434,614 ops/sec ±0.73% (97 runs sampled) -🤞 @shelacek/ubjson x 74,697 ops/sec ±5.70% (91 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 30,070 ops/sec ±0.10% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------- Short strings, 170 bytes -🤞 json-joy/json-pack UbjsonEncoder x 1,818,725 ops/sec ±0.64% (98 runs sampled) -🤞 @shelacek/ubjson x 63,728 ops/sec ±1.30% (88 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,007,266 ops/sec ±0.59% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder --------------------------------------------------------------------------------- Numbers, 136 bytes -🤞 json-joy/json-pack UbjsonEncoder x 4,132,602 ops/sec ±0.42% (100 runs sampled) -🤞 @shelacek/ubjson x 361,219 ops/sec ±0.78% (99 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 1,119,393 ops/sec ±0.14% (100 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder ---------------------------------------------------------------------------------- Tokens, 308 bytes -🤞 json-joy/json-pack UbjsonEncoder x 1,907,200 ops/sec ±0.25% (100 runs sampled) -🤞 @shelacek/ubjson x 258,382 ops/sec ±0.52% (100 runs sampled) -🤞 Buffer.from(JSON.stringify()) x 971,885 ops/sec ±0.81% (99 runs sampled) -Fastest is 🤞 json-joy/json-pack UbjsonEncoder -``` - -### Decoding - -Node v18: - -``` -npx ts-node benchmarks/json-pack/bench.ubjson.decoding.ts -=============================================================================== Benchmark: Encoding -Warmup: 1000x , Node.js: v18.16.0 , Arch: arm64 , CPU: Apple M1 ---------------------------------------------------------------------------- Small object, 331 bytes -👍 json-joy/json-pack UbjsonDecoder x 2,615,977 ops/sec ±0.16% (101 runs sampled) -👍 @shelacek/ubjson x 536,500 ops/sec ±1.09% (96 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder ------------------------------------------------------------------------- Typical object, 8911 bytes -👍 json-joy/json-pack UbjsonDecoder x 235,867 ops/sec ±0.29% (100 runs sampled) -👍 @shelacek/ubjson x 56,058 ops/sec ±1.43% (97 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder -------------------------------------------------------------------------- Large object, 36678 bytes -👍 json-joy/json-pack UbjsonDecoder x 73,598 ops/sec ±0.78% (99 runs sampled) -👍 @shelacek/ubjson x 18,320 ops/sec ±0.58% (99 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder -------------------------------------------------------------------- Very large object, 474391 bytes -👍 json-joy/json-pack UbjsonDecoder x 3,197 ops/sec ±0.10% (100 runs sampled) -👍 @shelacek/ubjson x 932 ops/sec ±1.42% (98 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder ------------------------------------------------------------------ Object with many keys, 8314 bytes -👍 json-joy/json-pack UbjsonDecoder x 98,536 ops/sec ±1.03% (98 runs sampled) -👍 @shelacek/ubjson x 35,345 ops/sec ±0.57% (100 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder ------------------------------------------------------------------------- String ladder, 36555 bytes -👍 json-joy/json-pack UbjsonDecoder x 250,466 ops/sec ±5.04% (93 runs sampled) -👍 @shelacek/ubjson x 68,201 ops/sec ±2.84% (91 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder -------------------------------------------------------------------------- Long strings, 85535 bytes -👍 json-joy/json-pack UbjsonDecoder x 102,333 ops/sec ±2.35% (96 runs sampled) -👍 @shelacek/ubjson x 79,448 ops/sec ±0.70% (95 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder -------------------------------------------------------------------------- Short strings, 1556 bytes -👍 json-joy/json-pack UbjsonDecoder x 899,484 ops/sec ±0.44% (96 runs sampled) -👍 @shelacek/ubjson x 156,232 ops/sec ±2.08% (95 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder --------------------------------------------------------------------------------- Numbers, 790 bytes -👍 json-joy/json-pack UbjsonDecoder x 3,313,595 ops/sec ±0.14% (99 runs sampled) -👍 @shelacek/ubjson x 430,527 ops/sec ±0.76% (95 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder ---------------------------------------------------------------------------------- Tokens, 471 bytes -👍 json-joy/json-pack UbjsonDecoder x 1,879,654 ops/sec ±0.20% (95 runs sampled) -👍 @shelacek/ubjson x 322,744 ops/sec ±0.39% (98 runs sampled) -Fastest is 👍 json-joy/json-pack UbjsonDecoder -``` diff --git a/src/json-pack/ubjson/UbjsonDecoder.ts b/src/json-pack/ubjson/UbjsonDecoder.ts deleted file mode 100644 index 927eb47120..0000000000 --- a/src/json-pack/ubjson/UbjsonDecoder.ts +++ /dev/null @@ -1,124 +0,0 @@ -import {Reader} from '../../util/buffers/Reader'; -import {JsonPackExtension} from '../JsonPackExtension'; -import {ERROR} from '../cbor/constants'; -import type {BinaryJsonDecoder, PackValue} from '../types'; - -export class UbjsonDecoder implements BinaryJsonDecoder { - public reader = new Reader(); - - public read(uint8: Uint8Array): PackValue { - this.reader.reset(uint8); - return this.readAny(); - } - - public decode(uint8: Uint8Array): unknown { - this.reader.reset(uint8); - return this.readAny(); - } - - public readAny(): PackValue { - const reader = this.reader; - const octet = reader.u8(); - switch (octet) { - case 0x5a: - return null; - case 0x54: - return true; - case 0x46: - return false; - case 0x55: - return reader.u8(); - case 0x69: - return reader.i8(); - case 0x49: { - const int = reader.view.getInt16(reader.x, false); - reader.x += 2; - return int; - } - case 0x6c: { - const int = reader.view.getInt32(reader.x, false); - reader.x += 4; - return int; - } - case 0x64: { - const num = reader.view.getFloat32(reader.x, false); - reader.x += 4; - return num; - } - case 0x44: { - const num = reader.view.getFloat64(reader.x, false); - reader.x += 8; - return num; - } - case 0x4c: { - const num = reader.view.getBigInt64(reader.x, false); - reader.x += 8; - return num; - } - case 0x53: - return reader.utf8(+(this.readAny() as number)); - case 0x43: - return String.fromCharCode(reader.u8()); - case 0x5b: { - const uint8 = reader.uint8; - const x = reader.x; - if (uint8[x] === 0x24 && uint8[x + 1] === 0x55 && uint8[x + 2] === 0x23) { - reader.x += 3; - const size = +(this.readAny() as number); - return reader.buf(size); - } - let type: number = -1; - if (uint8[x] === 0x24) { - reader.x++; - type = reader.u8(); - } - let count: number = -1; - if (uint8[x] === 0x23) { - reader.x++; - count = reader.u8(); - } - if (uint8[x] === 0x24) { - reader.x++; - type = reader.u8(); - } - if (count >= 0) { - let wordSize: number = 1; - switch (type) { - case 0x49: - wordSize = 2; - break; - case 0x6c: - case 0x64: - wordSize = 4; - break; - case 0x44: - case 0x4c: - wordSize = 8; - break; - } - return new JsonPackExtension(type, reader.buf(count * wordSize)); - } else { - const arr: PackValue[] = []; - while (uint8[reader.x] !== 0x5d) arr.push(this.readAny()); - reader.x++; - return arr; - } - } - case 0x7b: { - const uint8 = reader.uint8; - const obj: Record = {}; - while (uint8[reader.x] !== 0x7d) { - const keySize = +(this.readAny() as number); - const key = reader.utf8(keySize); - if (key === '__proto__') throw ERROR.UNEXPECTED_OBJ_KEY; - obj[key] = this.readAny(); - } - reader.x++; - return obj; - } - case 0x4e: - return undefined; - } - return; - } -} diff --git a/src/json-pack/ubjson/UbjsonEncoder.ts b/src/json-pack/ubjson/UbjsonEncoder.ts deleted file mode 100644 index 575be1d3fa..0000000000 --- a/src/json-pack/ubjson/UbjsonEncoder.ts +++ /dev/null @@ -1,231 +0,0 @@ -import type {IWriter, IWriterGrowable} from '../../util/buffers'; -import type {BinaryJsonEncoder, StreamingBinaryJsonEncoder} from '../types'; - -export class UbjsonEncoder implements BinaryJsonEncoder, StreamingBinaryJsonEncoder { - constructor(public readonly writer: IWriter & IWriterGrowable) {} - - public encode(value: unknown): Uint8Array { - const writer = this.writer; - writer.reset(); - this.writeAny(value); - return writer.flush(); - } - - public writeAny(value: unknown): void { - switch (typeof value) { - case 'boolean': - return this.writeBoolean(value); - case 'number': - return this.writeNumber(value as number); - case 'string': - return this.writeStr(value); - case 'object': { - if (value === null) return this.writeNull(); - const constructor = value.constructor; - switch (constructor) { - case Array: - return this.writeArr(value as unknown[]); - case Uint8Array: - return this.writeBin(value as Uint8Array); - default: - return this.writeObj(value as Record); - } - } - case 'bigint': - return this.writeBigInt(value as bigint); - case 'undefined': - return this.writeUndef(); - default: - return this.writeNull(); - } - } - - public writeNull(): void { - this.writer.u8(0x5a); - } - - public writeUndef(): void { - this.writer.u8(0x4e); - } - - public writeBoolean(bool: boolean): void { - this.writer.u8(bool ? 0x54 : 0x46); - } - - public writeNumber(num: number): void { - if (num >> 0 === num) return this.writeInteger(num); - this.writeFloat(num); - } - - public writeInteger(int: number): void { - const writer = this.writer; - if (int <= 0xff && 0 <= int) writer.u16(0x5500 | int); - else if (int <= 127 && -128 <= int) { - writer.u16(0x6900); - writer.view.setInt8(writer.x - 1, int); - } else if (int <= 32767 && -32768 <= int) { - writer.ensureCapacity(3); - writer.u8(0x49); - writer.view.setInt16(writer.x, int, false); - writer.x += 2; - } else if (int <= 2147483647 && -2147483648 <= int) { - writer.ensureCapacity(5); - writer.u8(0x6c); - writer.view.setInt32(writer.x, int, false); - writer.x += 4; - } - } - - public writeUInteger(uint: number): void { - const writer = this.writer; - if (uint < 0xff) writer.u16(0x5500 + uint); - } - - public writeFloat(float: number): void { - const writer = this.writer; - writer.ensureCapacity(9); - const view = writer.view; - const x = writer.x; - view.setUint8(x, 0x44); - view.setFloat64(x + 1, float, false); - writer.x = x + 9; - } - - public writeBigInt(int: bigint): void { - const writer = this.writer; - writer.ensureCapacity(9); - const view = writer.view; - const x = writer.x; - view.setUint8(x, 0x4c); - view.setBigInt64(x + 1, int, false); - writer.x = x + 9; - } - - public writeBin(buf: Uint8Array): void { - const writer = this.writer; - const length = buf.length; - writer.u32(0x5b_24_55_23); // "[$U#" - this.writeInteger(length); - writer.buf(buf, length); - } - - public writeStr(str: string): void { - const length = str.length; - const maxLength = length * 4; - const capacity = maxLength + 1 + 5; // 1 for string type, 5 for length. - const writer = this.writer; - writer.ensureCapacity(capacity); - const uint8 = writer.uint8; - uint8[writer.x++] = 0x53; - const x = writer.x; - const oneByteLength = maxLength < 0xff; - if (oneByteLength) { - uint8[writer.x++] = 0x55; - writer.x++; - } else { - uint8[writer.x++] = 0x6c; - writer.x += 4; - } - const size = writer.utf8(str); - if (oneByteLength) uint8[x + 1] = size; - else writer.view.setUint32(x + 1, size); - } - - public writeAsciiStr(str: string): void { - this.writeStr(str); - } - - public writeArr(arr: unknown[]): void { - const writer = this.writer; - writer.u8(0x5b); - const length = arr.length; - for (let i = 0; i < length; i++) this.writeAny(arr[i]); - writer.u8(0x5d); - } - - public writeObj(obj: Record): void { - const writer = this.writer; - const keys = Object.keys(obj); - const length = keys.length; - writer.u8(0x7b); - for (let i = 0; i < length; i++) { - const key = keys[i]; - const value = obj[key]; - this.writeKey(key); - this.writeAny(value); - } - writer.u8(0x7d); - } - - public writeKey(str: string): void { - const length = str.length; - const maxLength = length * 4; - const capacity = maxLength + 5; // 5 for int. - const writer = this.writer; - writer.ensureCapacity(capacity); - const uint8 = writer.uint8; - const x = writer.x; - const oneByteLength = maxLength < 0xff; - if (oneByteLength) { - uint8[writer.x++] = 0x55; - writer.x++; - } else { - uint8[writer.x++] = 0x6c; - writer.x += 4; - } - const size = writer.utf8(str); - if (oneByteLength) uint8[x + 1] = size; - else writer.view.setUint32(x + 1, size); - } - - // ------------------------------------------------------- Streaming encoding - - public writeStartStr(): void { - throw new Error('Method not implemented.'); - } - - public writeStrChunk(str: string): void { - throw new Error('Method not implemented.'); - } - - public writeEndStr(): void { - throw new Error('Method not implemented.'); - } - - public writeStartBin(): void { - throw new Error('Method not implemented.'); - } - - public writeBinChunk(buf: Uint8Array): void { - throw new Error('Method not implemented.'); - } - - public writeEndBin(): void { - throw new Error('Method not implemented.'); - } - - public writeStartArr(): void { - this.writer.u8(0x5b); - } - - public writeArrChunk(item: unknown): void { - this.writeAny(item); - } - - public writeEndArr(): void { - this.writer.u8(0x5d); - } - - public writeStartObj(): void { - this.writer.u8(0x7b); - } - - public writeObjChunk(key: string, value: unknown): void { - this.writeKey(key); - this.writeAny(value); - } - - public writeEndObj(): void { - this.writer.u8(0x7d); - } -} diff --git a/src/json-pack/ubjson/__tests__/UbjsonDecoder.spec.ts b/src/json-pack/ubjson/__tests__/UbjsonDecoder.spec.ts deleted file mode 100644 index 1799727d07..0000000000 --- a/src/json-pack/ubjson/__tests__/UbjsonDecoder.spec.ts +++ /dev/null @@ -1,198 +0,0 @@ -import {encode} from '@shelacek/ubjson'; -import {Writer} from '../../../util/buffers/Writer'; -import {PackValue} from '../../types'; -import {UbjsonEncoder} from '../UbjsonEncoder'; -import {UbjsonDecoder} from '../UbjsonDecoder'; -import {NullObject} from '../../../util/NullObject'; - -const encoder = new UbjsonEncoder(new Writer(8)); -const decoder = new UbjsonDecoder(); - -const assertEncoder = (value: PackValue, optimize = false) => { - const encoded1 = new Uint8Array(encode(value, {optimizeArrays: optimize, optimizeObjects: optimize})); - const encoded2 = encoder.encode(value); - // console.log(encoded1); - // console.log(encoded2); - const decoded1 = decoder.read(encoded1); - const decoded2 = decoder.read(encoded2); - expect(decoded1).toEqual(value); - expect(decoded2).toEqual(value); -}; - -describe('undefined', () => { - test('undefined', () => { - assertEncoder(undefined as any); - }); -}); - -describe('null', () => { - test('null', () => { - assertEncoder(null); - }); -}); - -describe('boolean', () => { - test('true', () => { - assertEncoder(true); - }); - - test('false', () => { - assertEncoder(false); - }); -}); - -describe('number', () => { - const ints = [ - 0, 1, -1, 123, -123, 1234, 3333, -3467, -4444, 55555, -55565, 234234, -322324, 2147483647, -1147483647, 12321321123, - -12321321123, +2321321123, - ]; - for (const int of ints) { - test('integer ' + int, () => { - assertEncoder(int); - }); - } - - test('floats', () => { - assertEncoder(0.0); - assertEncoder(1.1); - assertEncoder(-1.45); - assertEncoder(123.34); - assertEncoder(-123.234); - assertEncoder(-12321.321123); - assertEncoder(+2321321.123); - }); -}); - -describe('string', () => { - test('empty string', () => { - assertEncoder(''); - }); - - test('one char strings', () => { - assertEncoder('a'); - assertEncoder('b'); - assertEncoder('z'); - assertEncoder('~'); - assertEncoder('"'); - assertEncoder('\\'); - assertEncoder('*'); - assertEncoder('@'); - assertEncoder('9'); - assertEncoder('✅'); - assertEncoder('👍'); - }); - - test('short strings', () => { - assertEncoder('abc'); - assertEncoder('abc123'); - }); - - test('long strings', () => { - assertEncoder( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.', - ); - }); - - test('unsafe character in the middle of a string', () => { - assertEncoder('...................".....................'); - }); - - test('unsafe character in the middle of a string - 2', () => { - assertEncoder('...................🎉.....................'); - }); -}); - -describe('binary', () => { - test('empty buffer', () => { - assertEncoder(new Uint8Array(0), true); - }); - - test('small buffer', () => { - assertEncoder(new Uint8Array([1, 2, 3]), true); - }); -}); - -describe('array', () => { - test('empty array', () => { - assertEncoder([]); - }); - - test('array with one element', () => { - assertEncoder([1]); - }); - - test('array with two elements', () => { - assertEncoder([1, 2]); - }); - - test('array of array', () => { - assertEncoder([[123]]); - }); - - test('array of various types', () => { - assertEncoder([0, 1.32, 'str', true, false, null, [1, 2, 3]]); - }); -}); - -describe('object', () => { - test('empty object', () => { - assertEncoder({}); - }); - - test('object with one key', () => { - assertEncoder({foo: 'bar'}); - }); - - test('object with two keys', () => { - assertEncoder({foo: 'bar', baz: 123}); - }); - - test('object with various nested types', () => { - assertEncoder({ - '': null, - null: false, - true: true, - str: 'asdfasdf ,asdf asdf asdf asdf asdf, asdflkasjdflakjsdflajskdlfkasdf', - num: 123, - arr: [1, 2, 3], - obj: {foo: 'bar'}, - obj2: {1: 2, 3: 4}, - }); - }); - - test('throws on __proto__ key', () => { - const obj = new NullObject(); - // tslint:disable-next-line: no-string-literal - obj['__proto__'] = 123; - const buf = encoder.encode(obj); - expect(() => decoder.read(buf)).toThrow(); - }); -}); - -describe('nested object', () => { - test('large array/object', () => { - assertEncoder({ - foo: [ - 1, - 2, - 3, - { - looongLoooonnnngggg: 'bar', - looongLoooonnnngggg2: 'bar', - looongLoooonnnngggg3: 'bar', - looongLoooonnnngggg4: 'bar', - looongLoooonnnngggg5: 'bar', - looongLoooonnnngggg6: 'bar', - looongLoooonnnngggg7: 'bar', - someVeryVeryLongKeyNameSuperDuperLongKeyName: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName1: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName2: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName3: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName4: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName5: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName6: 'very very long value, I said, very very long value', - }, - ], - }); - }); -}); diff --git a/src/json-pack/ubjson/__tests__/UbjsonEncoder.spec.ts b/src/json-pack/ubjson/__tests__/UbjsonEncoder.spec.ts deleted file mode 100644 index 7fd4ffe5b7..0000000000 --- a/src/json-pack/ubjson/__tests__/UbjsonEncoder.spec.ts +++ /dev/null @@ -1,183 +0,0 @@ -import {decode} from '@shelacek/ubjson'; -import {Writer} from '../../../util/buffers/Writer'; -import {PackValue} from '../../types'; -import {UbjsonEncoder} from '../UbjsonEncoder'; - -const writer = new Writer(16); -const encoder = new UbjsonEncoder(writer); - -const assertEncoder = (value: PackValue, expected: PackValue = value) => { - const encoded1 = encoder.encode(value); - const decoded = decode(encoded1, {useTypedArrays: true}); - expect(decoded).toEqual(expected); -}; - -describe('undefined', () => { - test('undefined', () => { - assertEncoder(undefined as any); - }); -}); - -describe('null', () => { - test('null', () => { - assertEncoder(null); - }); -}); - -describe('boolean', () => { - test('true', () => { - assertEncoder(true); - }); - - test('false', () => { - assertEncoder(false); - }); -}); - -describe('number', () => { - const ints = [ - 0, 1, -1, 123, -123, 1234, 3333, -3467, -4444, 55555, -55565, 234234, -322324, 2147483647, -1147483647, 12321321123, - -12321321123, +2321321123, - ]; - for (const int of ints) { - test('integer ' + int, () => { - assertEncoder(int); - }); - } - - test('floats', () => { - assertEncoder(0.0); - assertEncoder(1.1); - assertEncoder(-1.45); - assertEncoder(123.34); - assertEncoder(-123.234); - assertEncoder(-12321.321123); - assertEncoder(+2321321.123); - }); -}); - -describe('string', () => { - test('empty string', () => { - assertEncoder(''); - }); - - test('one char strings', () => { - assertEncoder('a'); - assertEncoder('b'); - assertEncoder('z'); - assertEncoder('~'); - assertEncoder('"'); - assertEncoder('\\'); - assertEncoder('*'); - assertEncoder('@'); - assertEncoder('9'); - assertEncoder('✅'); - assertEncoder('👍'); - }); - - test('short strings', () => { - assertEncoder('abc'); - assertEncoder('abc123'); - }); - - test('long strings', () => { - assertEncoder( - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.', - ); - }); - - test('unsafe character in the middle of a string', () => { - assertEncoder('...................".....................'); - }); - - test('unsafe character in the middle of a string - 2', () => { - assertEncoder('...................🎉.....................'); - }); -}); - -describe('binary', () => { - test('empty buffer', () => { - assertEncoder(new Uint8Array(0)); - }); - - test('small buffer', () => { - assertEncoder(new Uint8Array([1, 2, 3])); - }); -}); - -describe('array', () => { - test('empty array', () => { - assertEncoder([]); - }); - - test('array with one element', () => { - assertEncoder([1]); - }); - - test('array with two elements', () => { - assertEncoder([1, 2]); - }); - - test('array of array', () => { - assertEncoder([[123]]); - }); - - test('array of various types', () => { - assertEncoder([0, 1.32, 'str', true, false, null, [1, 2, 3]]); - }); -}); - -describe('object', () => { - test('empty object', () => { - assertEncoder({}); - }); - - test('object with one key', () => { - assertEncoder({foo: 'bar'}); - }); - - test('object with two keys', () => { - assertEncoder({foo: 'bar', baz: 123}); - }); - - test('object with various nested types', () => { - assertEncoder({ - '': null, - null: false, - true: true, - str: 'asdfasdf ,asdf asdf asdf asdf asdf, asdflkasjdflakjsdflajskdlfkasdf', - num: 123, - arr: [1, 2, 3], - obj: {foo: 'bar'}, - obj2: {1: 2, 3: 4}, - }); - }); -}); - -describe('nested object', () => { - test('large array/object', () => { - assertEncoder({ - foo: [ - 1, - 2, - 3, - { - looongLoooonnnngggg: 'bar', - looongLoooonnnngggg2: 'bar', - looongLoooonnnngggg3: 'bar', - looongLoooonnnngggg4: 'bar', - looongLoooonnnngggg5: 'bar', - looongLoooonnnngggg6: 'bar', - looongLoooonnnngggg7: 'bar', - someVeryVeryLongKeyNameSuperDuperLongKeyName: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName1: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName2: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName3: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName4: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName5: 'very very long value, I said, very very long value', - someVeryVeryLongKeyNameSuperDuperLongKeyName6: 'very very long value, I said, very very long value', - }, - ], - }); - }); -}); diff --git a/src/json-pack/ubjson/__tests__/automated.spec.ts b/src/json-pack/ubjson/__tests__/automated.spec.ts deleted file mode 100644 index 718cc6c58b..0000000000 --- a/src/json-pack/ubjson/__tests__/automated.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {UbjsonEncoder} from '../UbjsonEncoder'; -import {UbjsonDecoder} from '../UbjsonDecoder'; -import {documents} from '../../../__tests__/json-documents'; -import {binaryDocuments} from '../../../__tests__/binary-documents'; - -const writer = new Writer(8); -const encoder = new UbjsonEncoder(writer); -const decoder = new UbjsonDecoder(); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - // const json = Buffer.from(encoded).toString('utf-8'); - // console.log('json', json); - decoder.reader.reset(encoded); - const decoded = decoder.readAny(); - expect(decoded).toEqual(value); -}; - -describe('Sample JSON documents', () => { - for (const t of documents) { - (t.only ? test.only : test)(t.name, () => { - assertEncoder(t.json as any); - }); - } -}); - -describe('Sample binary documents', () => { - for (const t of binaryDocuments) { - (t.only ? test.only : test)(t.name, () => { - assertEncoder(t.json as any); - }); - } -}); diff --git a/src/json-pack/ubjson/__tests__/fuzzer.spec.ts b/src/json-pack/ubjson/__tests__/fuzzer.spec.ts deleted file mode 100644 index d6830d5135..0000000000 --- a/src/json-pack/ubjson/__tests__/fuzzer.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {RandomJson} from '../../../json-random'; -import {Writer} from '../../../util/buffers/Writer'; -import {JsonValue} from '../../types'; -import {UbjsonEncoder} from '../UbjsonEncoder'; -import {UbjsonDecoder} from '../UbjsonDecoder'; - -const writer = new Writer(2); -const encoder = new UbjsonEncoder(writer); -const decoder = new UbjsonDecoder(); - -const assertEncoder = (value: JsonValue) => { - const encoded = encoder.encode(value); - const json = Buffer.from(encoded).toString('utf-8'); - try { - decoder.reader.reset(encoded); - const decoded = decoder.readAny(); - // console.log('decoded', decoded); - expect(decoded).toEqual(value); - } catch (error) { - /* tslint:disable no-console */ - console.log('value', value); - console.log('JSON.stringify', JSON.stringify(value)); - console.log('JsonEncoder', json); - /* tslint:enable no-console */ - throw error; - } -}; - -test('fuzzing', () => { - for (let i = 0; i < 1000; i++) { - const json = RandomJson.generate(); - assertEncoder(json); - } -}, 50000); - -test('big ints', () => { - for (let i = 0; i < 10; i++) { - const int = BigInt(Math.round(Math.random() * Number.MAX_SAFE_INTEGER)); - assertEncoder(int); - } -}); diff --git a/src/json-pack/util/CompressionTable.ts b/src/json-pack/util/CompressionTable.ts deleted file mode 100644 index d8218cb83c..0000000000 --- a/src/json-pack/util/CompressionTable.ts +++ /dev/null @@ -1,167 +0,0 @@ -import {JsonPackExtension} from '../JsonPackExtension'; - -const isSafeInteger = Number.isSafeInteger; - -export class CompressionTable { - public static create(value: unknown): CompressionTable { - const table = new CompressionTable(); - table.walk(value); - table.finalize(); - return table; - } - - protected integers = new Set(); - protected nonIntegers = new Set(); - - protected table: unknown[] = []; - protected map: Map = new Map(); - - public addInteger(int: number): void { - this.integers.add(int); - } - - public addLiteral(value: number | string | unknown): void { - if (isSafeInteger(value)) { - this.addInteger(value as number); - return; - } - this.nonIntegers.add(value); - } - - public walk(value: unknown): void { - switch (typeof value) { - case 'object': { - if (!value) return this.addLiteral(null); - const constructor = value.constructor; - switch (constructor) { - case Object: { - const obj = value as Record; - for (const key in obj) { - this.addLiteral(key); - this.walk(obj[key]); - } - break; - } - case Array: { - const arr = value as unknown[]; - const len = arr.length; - for (let i = 0; i < len; i++) this.walk(arr[i]); - break; - } - case Map: { - const map = value as Map; - map.forEach((value, key) => { - this.walk(key); - this.walk(value); - }); - break; - } - case Set: { - const set = value as Set; - set.forEach((value) => { - this.walk(value); - }); - break; - } - case JsonPackExtension: { - const ext = value as JsonPackExtension; - this.addInteger(ext.tag); - this.walk(ext.val); - } - } - return; - } - default: - return this.addLiteral(value); - } - } - - public finalize(): void { - const integers = Array.from(this.integers); - integers.sort((a, b) => a - b); - const len = integers.length; - const table = this.table; - const map = this.map; - if (len > 0) { - const first = integers[0]; - table.push(first); - map.set(first, 0); - let last = first; - for (let i = 1; i < len; i++) { - const int = integers[i]; - table.push(int - last); - map.set(int, i); - last = int; - } - } - const nonIntegers = Array.from(this.nonIntegers); - nonIntegers.sort(); - const lenNonIntegers = nonIntegers.length; - for (let i = 0; i < lenNonIntegers; i++) { - const value = nonIntegers[i]; - table.push(value); - map.set(value, len + i); - } - this.integers.clear(); - this.nonIntegers.clear(); - } - - public getIndex(value: unknown): number { - const index = this.map.get(value); - if (index === undefined) throw new Error(`Value [${value}] not found in compression table.`); - return index; - } - - public getTable(): unknown[] { - return this.table; - } - - public compress(value: unknown): unknown { - switch (typeof value) { - case 'object': { - if (!value) return this.getIndex(null); - const constructor = value.constructor; - switch (constructor) { - case Object: { - const obj = value as Record; - const newObj: Record = {}; - for (const key in obj) newObj[this.getIndex(key)] = this.compress(obj[key]); - return newObj; - } - case Array: { - const arr = value as unknown[]; - const newArr: unknown[] = []; - const len = arr.length; - for (let i = 0; i < len; i++) newArr.push(this.compress(arr[i])); - return newArr; - } - case Map: { - const map = value as Map; - const newMap = new Map(); - map.forEach((value, key) => { - newMap.set(this.compress(key), this.compress(value)); - }); - return newMap; - } - case Set: { - const set = value as Set; - const newSet = new Set(); - set.forEach((value) => { - newSet.add(this.compress(value)); - }); - break; - } - case JsonPackExtension: { - const ext = value as JsonPackExtension; - const newExt = new JsonPackExtension(this.getIndex(ext.tag), this.compress(ext.val)); - return newExt; - } - } - throw new Error('UNEXPECTED_OBJECT'); - } - default: { - return this.getIndex(value); - } - } - } -} diff --git a/src/json-pack/util/DecompressionTable.ts b/src/json-pack/util/DecompressionTable.ts deleted file mode 100644 index c1b40cf9b1..0000000000 --- a/src/json-pack/util/DecompressionTable.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {JsonPackExtension} from '../JsonPackExtension'; - -const isSafeInteger = Number.isSafeInteger; - -export class DecompressionTable { - protected readonly table: unknown[] = []; - - public importTable(rleTable: unknown[]) { - const length = rleTable.length; - if (!length) return; - const table = this.table; - const first = rleTable[0]; - table.push(first); - let i = 1; - if (isSafeInteger(first)) { - let prev: number = first; - let value: unknown; - while (i < length) { - value = rleTable[i]; - if (isSafeInteger(value)) { - prev = prev + value; - table.push(prev); - i++; - } else { - break; - } - } - } - while (i < length) table.push(rleTable[i++]); - } - - public getLiteral(index: number): unknown { - const table = this.table; - // if (index < 0 || index >= table.length) throw new Error('OUT_OF_BOUNDS'); - return table[index]; - } - - public decompress(value: unknown): unknown { - switch (typeof value) { - case 'number': { - return this.getLiteral(value); - } - case 'object': { - if (!value) return null; - const constructor = value.constructor; - switch (constructor) { - case Object: { - const obj = value as Record; - const newObj: Record = {}; - for (const key in obj) newObj[String(this.getLiteral(Number(key)))] = this.decompress(obj[key]); - return newObj; - } - case Array: { - const arr = value as unknown[]; - const newArr: unknown[] = []; - const len = arr.length; - for (let i = 0; i < len; i++) newArr.push(this.decompress(arr[i])); - return newArr; - } - case Map: { - const map = value as Map; - const newMap = new Map(); - map.forEach((value, key) => { - newMap.set(this.decompress(key), this.decompress(value)); - }); - return newMap; - } - case Set: { - const set = value as Set; - const newSet = new Set(); - set.forEach((value) => { - newSet.add(this.decompress(value)); - }); - break; - } - case JsonPackExtension: { - const ext = value as JsonPackExtension; - const newExt = new JsonPackExtension(Number(this.getLiteral(ext.tag)), this.decompress(ext.val)); - return newExt; - } - } - return value; - } - default: { - return value; - } - } - } -} diff --git a/src/json-pack/util/__tests__/CompressionTable.spec.ts b/src/json-pack/util/__tests__/CompressionTable.spec.ts deleted file mode 100644 index 6d3e5231fc..0000000000 --- a/src/json-pack/util/__tests__/CompressionTable.spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import {CompressionTable} from '../CompressionTable'; - -describe('.walk()', () => { - test('create a compression table from a primitive value', () => { - const table = CompressionTable.create(42).getTable(); - expect(table).toEqual([42]); - }); - - test('collects literals from object', () => { - const json = { - foo: 'bar', - baz: 42, - gg: 'foo', - true: false, - }; - const table = CompressionTable.create(json).getTable(); - expect(table).toEqual([42, 'bar', 'baz', false, 'foo', 'gg', 'true']); - }); - - test('run-length encodes integers', () => { - const json = { - foo: [-3, 12, 42, 12345], - baz: 42, - }; - const table = CompressionTable.create(json).getTable(); - expect(table).toEqual([-3, 15, 30, 12303, 'baz', 'foo']); - }); - - test('run-length encodes integers - 2', () => { - const json = { - foo: [5, 1, 2, 4, 8, 16, 17, 22], - baz: -1.5, - }; - const table = CompressionTable.create(json).getTable(); - expect(table).toEqual([1, 1, 2, 1, 3, 8, 1, 5, -1.5, 'baz', 'foo']); - }); -}); - -describe('.compress()', () => { - test('replaces literals with indices', () => { - const json = { - foo: 'bar', - baz: 42, - gg: 'foo', - true: false, - }; - const table = CompressionTable.create(json); - const compressed = table.compress(json); - expect(compressed).toEqual({'2': 0, '4': 1, '5': 4, '6': 3}); - }); - - test('can share compression table across two documents', () => { - const json1 = { - foo: 'bar', - }; - const json2 = { - foo: [0, 0, 5, 5], - }; - const table = new CompressionTable(); - table.walk(json1); - table.walk(json2); - table.finalize(); - const compressed1 = table.compress(json1); - const compressed2 = table.compress(json2); - expect(table.getTable()).toEqual([0, 5, 'bar', 'foo']); - expect(compressed1).toEqual({'3': 2}); - expect(compressed2).toEqual({'3': [0, 0, 1, 1]}); - }); -}); diff --git a/src/json-pack/util/__tests__/DecompressionTable.spec.ts b/src/json-pack/util/__tests__/DecompressionTable.spec.ts deleted file mode 100644 index 86b24bbea4..0000000000 --- a/src/json-pack/util/__tests__/DecompressionTable.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {CompressionTable} from '../CompressionTable'; -import {DecompressionTable} from '../DecompressionTable'; - -describe('.importTable()', () => { - test('can import back compression table', () => { - const json = { - a: [-10, -5, 5, 100], - b: [true, false, null, null], - c: 'c', - }; - const table = CompressionTable.create(json); - const decompressionTable = new DecompressionTable(); - decompressionTable.importTable(table.getTable()); - expect(decompressionTable.getLiteral(0)).toBe(-10); - expect(decompressionTable.getLiteral(1)).toBe(-5); - expect(decompressionTable.getLiteral(2)).toBe(5); - expect(decompressionTable.getLiteral(3)).toBe(100); - expect(decompressionTable.getLiteral(table.getIndex(true))).toBe(true); - expect(decompressionTable.getLiteral(table.getIndex(false))).toBe(false); - expect(decompressionTable.getLiteral(table.getIndex(null))).toBe(null); - expect(decompressionTable.getLiteral(table.getIndex('a'))).toBe('a'); - expect(decompressionTable.getLiteral(table.getIndex('b'))).toBe('b'); - expect(decompressionTable.getLiteral(table.getIndex('c'))).toBe('c'); - }); -}); - -describe('.decompress()', () => { - test('can decompress a document', () => { - const json = { - a: [-10, -5, 5, 100], - b: [true, false, null, null], - c: 'c', - }; - const table = CompressionTable.create(json); - const compressed = table.compress(json); - const decompressionTable = new DecompressionTable(); - decompressionTable.importTable(table.getTable()); - const decompressed = decompressionTable.decompress(compressed); - expect(decompressed).toEqual(json); - }); -}); diff --git a/src/json-pack/util/objKeyCmp.ts b/src/json-pack/util/objKeyCmp.ts deleted file mode 100644 index 18da990c7d..0000000000 --- a/src/json-pack/util/objKeyCmp.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const objKeyCmp = (a: string, b: string): number => { - const len1 = a.length; - const len2 = b.length; - return len1 === len2 ? (a > b ? 1 : -1) : len1 - len2; -}; diff --git a/src/json-patch/codec/binary/Decoder.ts b/src/json-patch/codec/binary/Decoder.ts index 0a26e6f770..8f747dc0bc 100644 --- a/src/json-patch/codec/binary/Decoder.ts +++ b/src/json-patch/codec/binary/Decoder.ts @@ -31,13 +31,13 @@ import { OpType, OpUndefined, } from '../../op'; -import {MsgPackDecoderFast} from '../../../json-pack/msgpack/MsgPackDecoderFast'; +import {MsgPackDecoderFast} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackDecoderFast'; import {OPCODE} from '../../constants'; import {Path} from '../../../json-pointer'; import {JsonPatchTypes} from '../json/types'; import {createMatcherDefault} from '../../util'; import type {JsonPatchOptions} from '../../types'; -import type {Reader} from '../../../util/buffers/Reader'; +import type {Reader} from '@jsonjoy.com/json-pack/lib/util/buffers/Reader'; export class Decoder extends MsgPackDecoderFast { constructor(private readonly options: JsonPatchOptions) { diff --git a/src/json-patch/codec/binary/Encoder.ts b/src/json-patch/codec/binary/Encoder.ts index 513ec1536d..9eabd67a54 100644 --- a/src/json-patch/codec/binary/Encoder.ts +++ b/src/json-patch/codec/binary/Encoder.ts @@ -1,4 +1,4 @@ -import {MsgPackEncoderFast as EncoderMessagePack} from '../../../json-pack/msgpack/MsgPackEncoderFast'; +import {MsgPackEncoderFast as EncoderMessagePack} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackEncoderFast'; import {Op} from '../../op'; export class Encoder extends EncoderMessagePack { diff --git a/src/json-patch/codec/binary/__tests__/message-pack.spec.ts b/src/json-patch/codec/binary/__tests__/message-pack.spec.ts index afef963c2e..40c555643d 100644 --- a/src/json-patch/codec/binary/__tests__/message-pack.spec.ts +++ b/src/json-patch/codec/binary/__tests__/message-pack.spec.ts @@ -5,7 +5,7 @@ import {encode as encodeCompact} from '../../compact'; import { MsgPackEncoderFast as MsgPackEncoder, MsgPackDecoderFast as MsgPackDecoder, -} from '../../../../json-pack/msgpack'; +} from '@jsonjoy.com/json-pack/lib/msgpack'; const msgPackEncoder = new MsgPackEncoder(); const msgPackDecoder = new MsgPackDecoder(); diff --git a/src/json-patch/op/AbstractOp.ts b/src/json-patch/op/AbstractOp.ts index e17cf6f7f3..65eb39d1df 100644 --- a/src/json-patch/op/AbstractOp.ts +++ b/src/json-patch/op/AbstractOp.ts @@ -3,7 +3,7 @@ import type {Path} from '../../json-pointer'; import type {OpType} from '../opcodes'; import type {Operation} from '../types'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; export abstract class AbstractOp { public readonly from?: Path; diff --git a/src/json-patch/op/OpAdd.ts b/src/json-patch/op/OpAdd.ts index b43b738912..6cb0f37295 100644 --- a/src/json-patch/op/OpAdd.ts +++ b/src/json-patch/op/OpAdd.ts @@ -4,7 +4,7 @@ import {OperationAdd} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {clone as deepClone} from '../../json-clone/clone'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpAnd.ts b/src/json-patch/op/OpAnd.ts index d5bb76d7b3..c61ec9b3a3 100644 --- a/src/json-patch/op/OpAnd.ts +++ b/src/json-patch/op/OpAnd.ts @@ -5,7 +5,7 @@ import {OperationAnd, PredicateOperation} from '../types'; import {OPCODE} from '../constants'; import {Path, formatJsonPointer} from '../../json-pointer'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpContains.ts b/src/json-patch/op/OpContains.ts index 94d33ff41d..d89fd3fd56 100644 --- a/src/json-patch/op/OpContains.ts +++ b/src/json-patch/op/OpContains.ts @@ -4,7 +4,7 @@ import {AbstractPredicateOp} from './AbstractPredicateOp'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpCopy.ts b/src/json-patch/op/OpCopy.ts index 340b67e32b..8103b38430 100644 --- a/src/json-patch/op/OpCopy.ts +++ b/src/json-patch/op/OpCopy.ts @@ -5,7 +5,7 @@ import {Path, find, formatJsonPointer} from '../../json-pointer'; import {OpAdd} from './OpAdd'; import {clone as deepClone} from '../../json-clone/clone'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpDefined.ts b/src/json-patch/op/OpDefined.ts index 43ae0465cb..40964220d9 100644 --- a/src/json-patch/op/OpDefined.ts +++ b/src/json-patch/op/OpDefined.ts @@ -4,7 +4,7 @@ import {OperationDefined} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpEnds.ts b/src/json-patch/op/OpEnds.ts index 206edfe56d..e1d4e391c4 100644 --- a/src/json-patch/op/OpEnds.ts +++ b/src/json-patch/op/OpEnds.ts @@ -4,7 +4,7 @@ import {OperationEnds} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpExtend.ts b/src/json-patch/op/OpExtend.ts index a4de9b747a..059f40b573 100644 --- a/src/json-patch/op/OpExtend.ts +++ b/src/json-patch/op/OpExtend.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationExtend} from '../types'; import {find, isArrayReference, isObjectReference, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; const {isArray} = Array; diff --git a/src/json-patch/op/OpFlip.ts b/src/json-patch/op/OpFlip.ts index 41c52bb3ab..a18fcafff7 100644 --- a/src/json-patch/op/OpFlip.ts +++ b/src/json-patch/op/OpFlip.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationFlip} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpIn.ts b/src/json-patch/op/OpIn.ts index 2b520abe10..385f5bae55 100644 --- a/src/json-patch/op/OpIn.ts +++ b/src/json-patch/op/OpIn.ts @@ -5,7 +5,7 @@ import {AbstractPredicateOp} from './AbstractPredicateOp'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; import {deepEqual} from '../../json-equal/deepEqual'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpInc.ts b/src/json-patch/op/OpInc.ts index 74f1acf6c0..47a1b12faa 100644 --- a/src/json-patch/op/OpInc.ts +++ b/src/json-patch/op/OpInc.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationInc} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpLess.ts b/src/json-patch/op/OpLess.ts index affe7307ea..7e4cb4d4c3 100644 --- a/src/json-patch/op/OpLess.ts +++ b/src/json-patch/op/OpLess.ts @@ -4,7 +4,7 @@ import {OperationLess} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpMatches.ts b/src/json-patch/op/OpMatches.ts index 0c070c9da3..da69abb740 100644 --- a/src/json-patch/op/OpMatches.ts +++ b/src/json-patch/op/OpMatches.ts @@ -4,7 +4,7 @@ import {AbstractPredicateOp} from './AbstractPredicateOp'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpMerge.ts b/src/json-patch/op/OpMerge.ts index 8a3b34336c..318e1b1b35 100644 --- a/src/json-patch/op/OpMerge.ts +++ b/src/json-patch/op/OpMerge.ts @@ -4,7 +4,7 @@ import {OperationMerge} from '../types'; import {find, isArrayReference, Path, formatJsonPointer} from '../../json-pointer'; import {isTextNode, isElementNode} from '../util'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpMore.ts b/src/json-patch/op/OpMore.ts index 9c96eea25a..42a46173a7 100644 --- a/src/json-patch/op/OpMore.ts +++ b/src/json-patch/op/OpMore.ts @@ -4,7 +4,7 @@ import {OperationMore} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpMove.ts b/src/json-patch/op/OpMove.ts index 5e5d487d38..082e9ea8f6 100644 --- a/src/json-patch/op/OpMove.ts +++ b/src/json-patch/op/OpMove.ts @@ -5,7 +5,7 @@ import {OpRemove} from './OpRemove'; import {OpAdd} from './OpAdd'; import {Path, toPath, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpNot.ts b/src/json-patch/op/OpNot.ts index ae9dcfaf1a..4211069e74 100644 --- a/src/json-patch/op/OpNot.ts +++ b/src/json-patch/op/OpNot.ts @@ -5,7 +5,7 @@ import {OperationNot, PredicateOperation} from '../types'; import {OPCODE} from '../constants'; import {Path, formatJsonPointer} from '../../json-pointer'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpOr.ts b/src/json-patch/op/OpOr.ts index c409b5eca8..cfc01dd9c7 100644 --- a/src/json-patch/op/OpOr.ts +++ b/src/json-patch/op/OpOr.ts @@ -5,7 +5,7 @@ import {OperationOr, PredicateOperation} from '../types'; import {OPCODE} from '../constants'; import {Path, formatJsonPointer} from '../../json-pointer'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpRemove.ts b/src/json-patch/op/OpRemove.ts index a5f9b53be8..c5f7674981 100644 --- a/src/json-patch/op/OpRemove.ts +++ b/src/json-patch/op/OpRemove.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationRemove} from '../types'; import {find, isObjectReference, isArrayReference, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpReplace.ts b/src/json-patch/op/OpReplace.ts index 1b6fa8695f..ffe9541c5f 100644 --- a/src/json-patch/op/OpReplace.ts +++ b/src/json-patch/op/OpReplace.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationReplace} from '../types'; import {find, isObjectReference, isArrayReference, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpSplit.ts b/src/json-patch/op/OpSplit.ts index ea7256b392..32b75d74fe 100644 --- a/src/json-patch/op/OpSplit.ts +++ b/src/json-patch/op/OpSplit.ts @@ -4,7 +4,7 @@ import {OperationSplit, SlateNode, SlateTextNode, SlateElementNode} from '../typ import {find, isObjectReference, isArrayReference, Path, formatJsonPointer} from '../../json-pointer'; import {isTextNode, isElementNode} from '../util'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; type Composable = string | number | SlateNode; diff --git a/src/json-patch/op/OpStarts.ts b/src/json-patch/op/OpStarts.ts index ad77ab4c3e..2ec2fee2d8 100644 --- a/src/json-patch/op/OpStarts.ts +++ b/src/json-patch/op/OpStarts.ts @@ -4,7 +4,7 @@ import {OperationStarts} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-patch/op/OpStrDel.ts b/src/json-patch/op/OpStrDel.ts index 67605d19dc..2efffb5722 100644 --- a/src/json-patch/op/OpStrDel.ts +++ b/src/json-patch/op/OpStrDel.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationStrDel} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpStrIns.ts b/src/json-patch/op/OpStrIns.ts index 6d56ba259c..0a714d07f0 100644 --- a/src/json-patch/op/OpStrIns.ts +++ b/src/json-patch/op/OpStrIns.ts @@ -3,7 +3,7 @@ import {AbstractOp} from './AbstractOp'; import {OperationStrIns} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpTest.ts b/src/json-patch/op/OpTest.ts index 71e2d31e37..3535c308d2 100644 --- a/src/json-patch/op/OpTest.ts +++ b/src/json-patch/op/OpTest.ts @@ -5,7 +5,7 @@ import {AbstractPredicateOp} from './AbstractPredicateOp'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; import {deepEqual} from '../../json-equal/deepEqual'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch diff --git a/src/json-patch/op/OpTestString.ts b/src/json-patch/op/OpTestString.ts index de7df7602f..a12d020a1e 100644 --- a/src/json-patch/op/OpTestString.ts +++ b/src/json-patch/op/OpTestString.ts @@ -4,7 +4,7 @@ import {OperationTestString} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpTestStringLen.ts b/src/json-patch/op/OpTestStringLen.ts index 5e302cf0ea..0cf7d346df 100644 --- a/src/json-patch/op/OpTestStringLen.ts +++ b/src/json-patch/op/OpTestStringLen.ts @@ -4,7 +4,7 @@ import {OperationTestStringLen} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Patch Extended diff --git a/src/json-patch/op/OpTestType.ts b/src/json-patch/op/OpTestType.ts index 4ec5d2c93e..b7cdc442f3 100644 --- a/src/json-patch/op/OpTestType.ts +++ b/src/json-patch/op/OpTestType.ts @@ -4,7 +4,7 @@ import {OperationTestType, JsTypes, JsonPatchTypes} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; const {isArray} = Array; diff --git a/src/json-patch/op/OpType.ts b/src/json-patch/op/OpType.ts index 49f701d800..9ce4b9b512 100644 --- a/src/json-patch/op/OpType.ts +++ b/src/json-patch/op/OpType.ts @@ -4,7 +4,7 @@ import {OperationType, JsonPatchTypes} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; const {isArray} = Array; diff --git a/src/json-patch/op/OpUndefined.ts b/src/json-patch/op/OpUndefined.ts index 4d34bf8a24..bd41a7f2d5 100644 --- a/src/json-patch/op/OpUndefined.ts +++ b/src/json-patch/op/OpUndefined.ts @@ -4,7 +4,7 @@ import {OperationUndefined} from '../types'; import {find, Path, formatJsonPointer} from '../../json-pointer'; import {OPCODE} from '../constants'; import {AbstractOp} from './AbstractOp'; -import type {IMessagePackEncoder} from '../../json-pack/msgpack'; +import type {IMessagePackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; /** * @category JSON Predicate diff --git a/src/json-random/RandomJson.ts b/src/json-random/RandomJson.ts index ba37c709ff..aa4c00fee9 100644 --- a/src/json-random/RandomJson.ts +++ b/src/json-random/RandomJson.ts @@ -1,4 +1,4 @@ -import type {JsonValue} from '../json-pack/types'; +import type {JsonValue} from '@jsonjoy.com/json-pack/lib/types'; /** @ignore */ export type NodeType = 'null' | 'boolean' | 'number' | 'string' | 'binary' | 'array' | 'object'; diff --git a/src/json-size/__tests__/fuzz.spec.ts b/src/json-size/__tests__/fuzz.spec.ts index aa1c2f01fd..5a067411e2 100644 --- a/src/json-size/__tests__/fuzz.spec.ts +++ b/src/json-size/__tests__/fuzz.spec.ts @@ -1,6 +1,6 @@ import {jsonSize} from '..'; import {RandomJson} from '../../json-random/RandomJson'; -import {utf8Size} from '../../util/strings/utf8'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; const random = new RandomJson(); const iterations = 100; diff --git a/src/json-size/__tests__/msgpackSizeFast.spec.ts b/src/json-size/__tests__/msgpackSizeFast.spec.ts index d35951abd3..50db96fd3c 100644 --- a/src/json-size/__tests__/msgpackSizeFast.spec.ts +++ b/src/json-size/__tests__/msgpackSizeFast.spec.ts @@ -1,4 +1,4 @@ -import {JsonPackExtension, JsonPackValue} from '../../json-pack/msgpack'; +import {JsonPackExtension, JsonPackValue} from '@jsonjoy.com/json-pack/lib/msgpack'; import {msgpackSizeFast} from '../msgpackSizeFast'; test('computes size of single values', () => { diff --git a/src/json-size/__tests__/testJsonSize.ts b/src/json-size/__tests__/testJsonSize.ts index 1240a9a6b4..eeae004be2 100644 --- a/src/json-size/__tests__/testJsonSize.ts +++ b/src/json-size/__tests__/testJsonSize.ts @@ -1,4 +1,4 @@ -import {utf8Size} from '../../util/strings/utf8'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; export const testJsonSize = ( jsonSize: (val: unknown) => number, diff --git a/src/json-size/json.ts b/src/json-size/json.ts index 9405609e3f..c75f7b41d5 100644 --- a/src/json-size/json.ts +++ b/src/json-size/json.ts @@ -1,4 +1,4 @@ -import {utf8Size} from '../util/strings/utf8'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; const numberSize = (num: number) => { const isInteger = num === Math.round(num); diff --git a/src/json-size/msgpackSizeFast.ts b/src/json-size/msgpackSizeFast.ts index ae6bc5b37a..8ddd87a2a5 100644 --- a/src/json-size/msgpackSizeFast.ts +++ b/src/json-size/msgpackSizeFast.ts @@ -1,5 +1,5 @@ -import {JsonPackExtension, JsonPackValue} from '../json-pack/msgpack'; -import {isUint8Array} from '../util/buffers/isUint8Array'; +import {JsonPackExtension, JsonPackValue} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {isUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/isUint8Array'; const arraySize = (arr: unknown[]): number => { let size = 2; diff --git a/src/json-stable/index.ts b/src/json-stable/index.ts index 613d76c643..74a0e51be4 100644 --- a/src/json-stable/index.ts +++ b/src/json-stable/index.ts @@ -1,4 +1,4 @@ -import {escape} from '../util/strings/escape'; +import {escape} from '@jsonjoy.com/json-pack/lib/util/strings/escape'; import {sort} from '../util/sort/insertion'; import type {json_string} from '../json-brand'; diff --git a/src/json-type-cli/Cli.ts b/src/json-type-cli/Cli.ts index f073724a6f..83dedaecca 100644 --- a/src/json-type-cli/Cli.ts +++ b/src/json-type-cli/Cli.ts @@ -1,7 +1,7 @@ import {parseArgs} from 'node:util'; import {TypeSystem} from '../json-type/system/TypeSystem'; import {ObjectValueCaller} from '../reactive-rpc/common/rpc/caller/ObjectValueCaller'; -import {bufferToUint8Array} from '../util/buffers/bufferToUint8Array'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; import {formatError} from './util'; import {defineBuiltinRoutes} from './methods'; import {defaultParams} from './defaultParams'; diff --git a/src/json-type-cli/codecs/cbor.ts b/src/json-type-cli/codecs/cbor.ts index 50e797c4b0..6174b2fbbf 100644 --- a/src/json-type-cli/codecs/cbor.ts +++ b/src/json-type-cli/codecs/cbor.ts @@ -1,6 +1,6 @@ -import {CborDecoder} from '../../json-pack/cbor/CborDecoder'; -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; -import type {Writer} from '../../util/buffers/Writer'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import type {CliCodec} from '../types'; export class CliCodecCbor implements CliCodec<'cbor'> { diff --git a/src/json-type-cli/codecs/json.ts b/src/json-type-cli/codecs/json.ts index 14db037a96..fad83b3069 100644 --- a/src/json-type-cli/codecs/json.ts +++ b/src/json-type-cli/codecs/json.ts @@ -1,6 +1,6 @@ -import {JsonDecoder} from '../../json-pack/json/JsonDecoder'; -import {JsonEncoder} from '../../json-pack/json/JsonEncoder'; -import type {Writer} from '../../util/buffers/Writer'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import type {CliCodec} from '../types'; export class CliCodecJson implements CliCodec<'json'> { diff --git a/src/json-type-cli/codecs/json2.ts b/src/json-type-cli/codecs/json2.ts index 00f48fcf5b..d9df7f99d7 100644 --- a/src/json-type-cli/codecs/json2.ts +++ b/src/json-type-cli/codecs/json2.ts @@ -1,7 +1,7 @@ -import {JsonDecoder} from '../../json-pack/json/JsonDecoder'; -import {JsonEncoder} from '../../json-pack/json/JsonEncoder'; -import {bufferToUint8Array} from '../../util/buffers/bufferToUint8Array'; -import type {Writer} from '../../util/buffers/Writer'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import type {CliCodec} from '../types'; /** diff --git a/src/json-type-cli/codecs/json4.ts b/src/json-type-cli/codecs/json4.ts index 6ea7aaf074..1d290ec3b4 100644 --- a/src/json-type-cli/codecs/json4.ts +++ b/src/json-type-cli/codecs/json4.ts @@ -1,7 +1,7 @@ -import {JsonDecoder} from '../../json-pack/json/JsonDecoder'; -import {JsonEncoder} from '../../json-pack/json/JsonEncoder'; -import type {Writer} from '../../util/buffers/Writer'; -import {bufferToUint8Array} from '../../util/buffers/bufferToUint8Array'; +import {JsonDecoder} from '@jsonjoy.com/json-pack/lib/json/JsonDecoder'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; import type {CliCodec} from '../types'; /** diff --git a/src/json-type-cli/codecs/msgpack.ts b/src/json-type-cli/codecs/msgpack.ts index 08dd401ced..95cb5ab8ef 100644 --- a/src/json-type-cli/codecs/msgpack.ts +++ b/src/json-type-cli/codecs/msgpack.ts @@ -1,6 +1,6 @@ -import {MsgPackEncoder} from '../../json-pack/msgpack'; -import {MsgPackDecoder} from '../../json-pack/msgpack/MsgPackDecoder'; -import type {Writer} from '../../util/buffers/Writer'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {MsgPackDecoder} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackDecoder'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import type {CliCodec} from '../types'; export class CliCodecMsgpack implements CliCodec<'msgpack'> { diff --git a/src/json-type-cli/codecs/ubjson.ts b/src/json-type-cli/codecs/ubjson.ts index a9fe737242..bad4036c81 100644 --- a/src/json-type-cli/codecs/ubjson.ts +++ b/src/json-type-cli/codecs/ubjson.ts @@ -1,6 +1,6 @@ -import {UbjsonDecoder} from '../../json-pack/ubjson/UbjsonDecoder'; -import {UbjsonEncoder} from '../../json-pack/ubjson/UbjsonEncoder'; -import type {Writer} from '../../util/buffers/Writer'; +import {UbjsonDecoder} from '@jsonjoy.com/json-pack/lib/ubjson/UbjsonDecoder'; +import {UbjsonEncoder} from '@jsonjoy.com/json-pack/lib/ubjson/UbjsonEncoder'; +import type {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import type {CliCodec} from '../types'; export class CliCodecUbjson implements CliCodec<'ubjson'> { diff --git a/src/json-type-cli/defaultCodecs.ts b/src/json-type-cli/defaultCodecs.ts index aeb6f210bb..c6511a13d8 100644 --- a/src/json-type-cli/defaultCodecs.ts +++ b/src/json-type-cli/defaultCodecs.ts @@ -1,4 +1,4 @@ -import {Writer} from '../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {CliCodecs} from './CliCodecs'; import {CliCodecCbor} from './codecs/cbor'; import {CliCodecJson} from './codecs/json'; diff --git a/src/json-type-cli/params/CliParamCmd.ts b/src/json-type-cli/params/CliParamCmd.ts index 3488bfdc29..f685c40746 100644 --- a/src/json-type-cli/params/CliParamCmd.ts +++ b/src/json-type-cli/params/CliParamCmd.ts @@ -1,8 +1,8 @@ import {applyPatch} from '../../json-patch'; import {spawn} from 'child_process'; import {find, toPath, validateJsonPointer} from '../../json-pointer'; -import {bufferToUint8Array} from '../../util/buffers/bufferToUint8Array'; -import {listToUint8} from '../../util/buffers/concat'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; +import {listToUint8} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; import type {Cli} from '../Cli'; import type {CliParam, CliParamInstance} from '../types'; diff --git a/src/json-type-value/Value.ts b/src/json-type-value/Value.ts index 165a67f0bb..b89c621053 100644 --- a/src/json-type-value/Value.ts +++ b/src/json-type-value/Value.ts @@ -1,4 +1,4 @@ -import type {JsonValueCodec} from '../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {ResolveType, Type} from '../json-type'; export class Value { diff --git a/src/json-type/__demos__/json-type.ts b/src/json-type/__demos__/json-type.ts index d96276c6c9..6a416d75a1 100644 --- a/src/json-type/__demos__/json-type.ts +++ b/src/json-type/__demos__/json-type.ts @@ -6,7 +6,7 @@ /* tslint:disable no-console */ -import {EncodingFormat} from '../../json-pack/constants'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; import {TypeSystem} from '../../json-type'; console.clear(); diff --git a/src/json-type/codegen/binary/BinaryEncoderCodegenContext.ts b/src/json-type/codegen/binary/BinaryEncoderCodegenContext.ts index 62bb5d5480..b21d988fe8 100644 --- a/src/json-type/codegen/binary/BinaryEncoderCodegenContext.ts +++ b/src/json-type/codegen/binary/BinaryEncoderCodegenContext.ts @@ -1,11 +1,11 @@ import {Codegen, CodegenStepExecJs} from '../../../util/codegen'; import {WriteBlobStep} from '../WriteBlobStep'; -import {concat} from '../../../util/buffers/concat'; +import {concat} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; import {Value} from '../../../json-type-value/Value'; import type {TypeSystem} from '../../system'; import type {Type} from '../../type'; import type {CompiledBinaryEncoder} from '../types'; -import type {BinaryJsonEncoder} from '../../../json-pack/types'; +import type {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; type Step = WriteBlobStep | CodegenStepExecJs; diff --git a/src/json-type/codegen/binary/CborEncoderCodegenContext.ts b/src/json-type/codegen/binary/CborEncoderCodegenContext.ts index 325edea30a..94923f4412 100644 --- a/src/json-type/codegen/binary/CborEncoderCodegenContext.ts +++ b/src/json-type/codegen/binary/CborEncoderCodegenContext.ts @@ -1,4 +1,4 @@ -import type {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; +import type {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {BinaryEncoderCodegenContext, type BinaryEncoderCodegenContextOptions} from './BinaryEncoderCodegenContext'; export interface CborEncoderCodegenContextOptions extends BinaryEncoderCodegenContextOptions {} diff --git a/src/json-type/codegen/binary/JsonEncoderCodegenContext.ts b/src/json-type/codegen/binary/JsonEncoderCodegenContext.ts index a1c193c0b6..bea35022d1 100644 --- a/src/json-type/codegen/binary/JsonEncoderCodegenContext.ts +++ b/src/json-type/codegen/binary/JsonEncoderCodegenContext.ts @@ -1,4 +1,4 @@ -import type {JsonEncoder} from '../../../json-pack/json/JsonEncoder'; +import type {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import {BinaryEncoderCodegenContext, type BinaryEncoderCodegenContextOptions} from './BinaryEncoderCodegenContext'; export interface JsonEncoderCodegenContextOptions extends BinaryEncoderCodegenContextOptions {} diff --git a/src/json-type/codegen/binary/MessagePackEncoderCodegenContext.ts b/src/json-type/codegen/binary/MessagePackEncoderCodegenContext.ts index 00c917413e..0583134e39 100644 --- a/src/json-type/codegen/binary/MessagePackEncoderCodegenContext.ts +++ b/src/json-type/codegen/binary/MessagePackEncoderCodegenContext.ts @@ -1,4 +1,4 @@ -import type {MsgPackEncoder} from '../../../json-pack/msgpack/MsgPackEncoder'; +import type {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackEncoder'; import {BinaryEncoderCodegenContext, type BinaryEncoderCodegenContextOptions} from './BinaryEncoderCodegenContext'; export interface MessagePackEncoderCodegenContextOptions extends BinaryEncoderCodegenContextOptions {} diff --git a/src/json-type/codegen/binary/__tests__/CborEncoderCodegenContext.spec.ts b/src/json-type/codegen/binary/__tests__/CborEncoderCodegenContext.spec.ts index 9e773fafbe..2c56ad4c02 100644 --- a/src/json-type/codegen/binary/__tests__/CborEncoderCodegenContext.spec.ts +++ b/src/json-type/codegen/binary/__tests__/CborEncoderCodegenContext.spec.ts @@ -1,10 +1,10 @@ import {TypeSystem} from '../../../system'; -import {CborEncoder} from '../../../../json-pack/cbor/CborEncoder'; -import {CborDecoder} from '../../../../json-pack/cbor/CborDecoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {Type} from '../../../type'; import {testBinaryCodegen} from './testBinaryCodegen'; -import {EncodingFormat} from '../../../../json-pack/constants'; -import {Writer} from '../../../../util/buffers/Writer'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; const writer = new Writer(1); const encoder = new CborEncoder(writer); diff --git a/src/json-type/codegen/binary/__tests__/JsonEncoderCodegenContext.spec.ts b/src/json-type/codegen/binary/__tests__/JsonEncoderCodegenContext.spec.ts index eb713de584..5ef8d2067d 100644 --- a/src/json-type/codegen/binary/__tests__/JsonEncoderCodegenContext.spec.ts +++ b/src/json-type/codegen/binary/__tests__/JsonEncoderCodegenContext.spec.ts @@ -1,9 +1,9 @@ import {TypeSystem} from '../../../system'; import {Type} from '../../../type'; import {testBinaryCodegen} from './testBinaryCodegen'; -import {EncodingFormat} from '../../../../json-pack/constants'; -import {JsonEncoder} from '../../../../json-pack/json/JsonEncoder'; -import {Writer} from '../../../../util/buffers/Writer'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {parse} from '../../../../json-binary'; const encoder = new JsonEncoder(new Writer(16)); diff --git a/src/json-type/codegen/binary/__tests__/MessagePackEncoderCodegenContext.spec.ts b/src/json-type/codegen/binary/__tests__/MessagePackEncoderCodegenContext.spec.ts index 59bf233cbf..e7f4cba553 100644 --- a/src/json-type/codegen/binary/__tests__/MessagePackEncoderCodegenContext.spec.ts +++ b/src/json-type/codegen/binary/__tests__/MessagePackEncoderCodegenContext.spec.ts @@ -1,10 +1,10 @@ import {TypeSystem} from '../../../system'; -import {MsgPackEncoder} from '../../../../json-pack/msgpack/MsgPackEncoder'; -import {MsgPackDecoder} from '../../../../json-pack/msgpack/MsgPackDecoder'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackEncoder'; +import {MsgPackDecoder} from '@jsonjoy.com/json-pack/lib/msgpack/MsgPackDecoder'; import {Type} from '../../../type'; import {testBinaryCodegen} from './testBinaryCodegen'; -import {EncodingFormat} from '../../../../json-pack/constants'; -import {Writer} from '../../../../util/buffers/Writer'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; const writer = new Writer(64); const encoder = new MsgPackEncoder(writer); diff --git a/src/json-type/codegen/json/JsonTextEncoderCodegenContext.ts b/src/json-type/codegen/json/JsonTextEncoderCodegenContext.ts index 1d8d8d66de..21b3a9d705 100644 --- a/src/json-type/codegen/json/JsonTextEncoderCodegenContext.ts +++ b/src/json-type/codegen/json/JsonTextEncoderCodegenContext.ts @@ -1,6 +1,6 @@ import {Codegen, CodegenStepExecJs} from '../../../util/codegen'; -import {asString} from '../../../util/strings/asString'; -import {toBase64} from '../../../util/base64'; +import {asString} from '@jsonjoy.com/json-pack/lib/util/strings/asString'; +import {toBase64} from '@jsonjoy.com/base64/lib/toBase64'; import type {TypeSystem} from '../../system'; import type {Type} from '../../type'; import type {json_string} from '../../../json-brand'; diff --git a/src/json-type/codegen/types.ts b/src/json-type/codegen/types.ts index 4bb281d82a..ac8f6dd65a 100644 --- a/src/json-type/codegen/types.ts +++ b/src/json-type/codegen/types.ts @@ -1,3 +1,3 @@ -import {BinaryJsonEncoder} from '../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; export type CompiledBinaryEncoder = (value: unknown, encoder: BinaryJsonEncoder) => void; diff --git a/src/json-type/type/classes/AbstractType.ts b/src/json-type/type/classes/AbstractType.ts index 12fdc3d5c8..14232589c0 100644 --- a/src/json-type/type/classes/AbstractType.ts +++ b/src/json-type/type/classes/AbstractType.ts @@ -18,23 +18,23 @@ import { JsonEncoderCodegenContext, JsonEncoderCodegenContextOptions, } from '../../codegen/binary/JsonEncoderCodegenContext'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import { MessagePackEncoderCodegenContext, MessagePackEncoderCodegenContextOptions, } from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {MsgPackEncoder} from '../../../json-pack/msgpack'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; import {lazy} from '../../../util/lazyFunction'; -import {EncodingFormat} from '../../../json-pack/constants'; -import {JsonEncoder} from '../../../json-pack/json/JsonEncoder'; -import {Writer} from '../../../util/buffers/Writer'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import { CapacityEstimatorCodegenContext, CapacityEstimatorCodegenContextOptions, CompiledCapacityEstimator, } from '../../codegen/capacity/CapacityEstimatorCodegenContext'; -import {JsonValueCodec} from '../../../json-pack/codecs/types'; +import {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type * as jsonSchema from '../../../json-schema'; import type {BaseType} from '../types'; import type {TypeSystem} from '../../system/TypeSystem'; diff --git a/src/json-type/type/classes/AnyType.ts b/src/json-type/type/classes/AnyType.ts index 1bd35812a2..0efd7d4ec6 100644 --- a/src/json-type/type/classes/AnyType.ts +++ b/src/json-type/type/classes/AnyType.ts @@ -7,10 +7,10 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {EncodingFormat} from '../../../json-pack/constants'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {AbstractType} from './AbstractType'; import type * as jsonSchema from '../../../json-schema'; diff --git a/src/json-type/type/classes/ArrayType.ts b/src/json-type/type/classes/ArrayType.ts index ab20ab3a39..f1b1dd969e 100644 --- a/src/json-type/type/classes/ArrayType.ts +++ b/src/json-type/type/classes/ArrayType.ts @@ -8,9 +8,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/BinaryType.ts b/src/json-type/type/classes/BinaryType.ts index bb5edd39a1..dc98969d19 100644 --- a/src/json-type/type/classes/BinaryType.ts +++ b/src/json-type/type/classes/BinaryType.ts @@ -10,9 +10,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/BooleanType.ts b/src/json-type/type/classes/BooleanType.ts index 0bbd56f726..9697fa2aef 100644 --- a/src/json-type/type/classes/BooleanType.ts +++ b/src/json-type/type/classes/BooleanType.ts @@ -8,9 +8,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/ConstType.ts b/src/json-type/type/classes/ConstType.ts index b674173f44..533ff44380 100644 --- a/src/json-type/type/classes/ConstType.ts +++ b/src/json-type/type/classes/ConstType.ts @@ -9,9 +9,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {maxEncodingCapacity} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/MapType.ts b/src/json-type/type/classes/MapType.ts index f75afc0497..61355bcb8a 100644 --- a/src/json-type/type/classes/MapType.ts +++ b/src/json-type/type/classes/MapType.ts @@ -1,7 +1,7 @@ import * as schema from '../../schema'; import {RandomJson} from '../../../json-random'; import {printTree} from '../../../util/print/printTree'; -import {asString} from '../../../util/strings/asString'; +import {asString} from '@jsonjoy.com/json-pack/lib/util/strings/asString'; import {validateTType} from '../../schema/validate'; import {ValidatorCodegenContext} from '../../codegen/validator/ValidatorCodegenContext'; import {ValidationPath} from '../../codegen/validator/types'; @@ -10,9 +10,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/NumberType.ts b/src/json-type/type/classes/NumberType.ts index 4b63f9c855..fed3fd990f 100644 --- a/src/json-type/type/classes/NumberType.ts +++ b/src/json-type/type/classes/NumberType.ts @@ -8,9 +8,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/ObjectType.ts b/src/json-type/type/classes/ObjectType.ts index 4bb3881893..f1b5822449 100644 --- a/src/json-type/type/classes/ObjectType.ts +++ b/src/json-type/type/classes/ObjectType.ts @@ -1,17 +1,17 @@ import * as schema from '../../schema'; import {RandomJson} from '../../../json-random'; import {printTree} from '../../../util/print/printTree'; -import {asString} from '../../../util/strings/asString'; +import {asString} from '@jsonjoy.com/json-pack/lib/util/strings/asString'; import {validateTType, validateWithValidator} from '../../schema/validate'; import {ValidatorCodegenContext} from '../../codegen/validator/ValidatorCodegenContext'; import {ValidationPath} from '../../codegen/validator/types'; import {ValidationError} from '../../constants'; -import {normalizeAccessor} from '../../../util/codegen/util/normalizeAccessor'; +import {normalizeAccessor} from '@jsonjoy.com/json-pack/lib/util/codegen/util/normalizeAccessor'; import {canSkipObjectKeyUndefinedCheck} from '../../codegen/validator/util'; import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderCodegenContext'; import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead, maxEncodingCapacity} from '../../../json-size'; diff --git a/src/json-type/type/classes/OrType.ts b/src/json-type/type/classes/OrType.ts index 97d37bc7ac..28c01bda53 100644 --- a/src/json-type/type/classes/OrType.ts +++ b/src/json-type/type/classes/OrType.ts @@ -8,9 +8,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {JsonExpressionCodegen} from '../../../json-expression'; import {operatorsMap} from '../../../json-expression/operators'; diff --git a/src/json-type/type/classes/RefType.ts b/src/json-type/type/classes/RefType.ts index be1033e66f..8eaa3dea86 100644 --- a/src/json-type/type/classes/RefType.ts +++ b/src/json-type/type/classes/RefType.ts @@ -8,10 +8,10 @@ import {CompiledBinaryEncoder} from '../../codegen/types'; import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {EncodingFormat} from '../../../json-pack/constants'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {AbstractType} from './AbstractType'; import type * as jsonSchema from '../../../json-schema'; diff --git a/src/json-type/type/classes/StringType.ts b/src/json-type/type/classes/StringType.ts index 697622f645..fda53ff6b3 100644 --- a/src/json-type/type/classes/StringType.ts +++ b/src/json-type/type/classes/StringType.ts @@ -1,6 +1,6 @@ import * as schema from '../../schema'; import {RandomJson} from '../../../json-random'; -import {asString} from '../../../util/strings/asString'; +import {asString} from '@jsonjoy.com/json-pack/lib/util/strings/asString'; import {validateMinMax, validateTType, validateWithValidator} from '../../schema/validate'; import {ValidatorCodegenContext} from '../../codegen/validator/ValidatorCodegenContext'; import {ValidationPath} from '../../codegen/validator/types'; @@ -9,9 +9,9 @@ import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderC import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; import {BinaryEncoderCodegenContext} from '../../codegen/binary/BinaryEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; -import {BinaryJsonEncoder} from '../../../json-pack/types'; +import {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; import {AbstractType} from './AbstractType'; diff --git a/src/json-type/type/classes/TupleType.ts b/src/json-type/type/classes/TupleType.ts index 3aed7324af..5adea83dd8 100644 --- a/src/json-type/type/classes/TupleType.ts +++ b/src/json-type/type/classes/TupleType.ts @@ -7,7 +7,7 @@ import {ValidationError} from '../../constants'; import {JsonTextEncoderCodegenContext} from '../../codegen/json/JsonTextEncoderCodegenContext'; import {CborEncoderCodegenContext} from '../../codegen/binary/CborEncoderCodegenContext'; import {JsonEncoderCodegenContext} from '../../codegen/binary/JsonEncoderCodegenContext'; -import {JsExpression} from '../../../util/codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {MessagePackEncoderCodegenContext} from '../../codegen/binary/MessagePackEncoderCodegenContext'; import {CapacityEstimatorCodegenContext} from '../../codegen/capacity/CapacityEstimatorCodegenContext'; import {MaxEncodingOverhead} from '../../../json-size'; diff --git a/src/json-type/typescript/toText.ts b/src/json-type/typescript/toText.ts index 4e3710eb57..9c40ba6dd9 100644 --- a/src/json-type/typescript/toText.ts +++ b/src/json-type/typescript/toText.ts @@ -1,4 +1,4 @@ -import {wordWrap} from '../../util/strings/wordWrap'; +import {wordWrap} from '@jsonjoy.com/json-pack/lib/util/strings/wordWrap'; import {TsIdentifier, TsNode, TsParameter} from './types'; import {TAB, isSimpleType, normalizeKey} from './util'; diff --git a/src/reactive-rpc/__tests__/e2e/uws/http/FetchRpcClient.spec.ts b/src/reactive-rpc/__tests__/e2e/uws/http/FetchRpcClient.spec.ts index b989653b43..037105b016 100644 --- a/src/reactive-rpc/__tests__/e2e/uws/http/FetchRpcClient.spec.ts +++ b/src/reactive-rpc/__tests__/e2e/uws/http/FetchRpcClient.spec.ts @@ -5,10 +5,10 @@ import {ApiTestSetup, runApiTests} from '../../../../common/rpc/__tests__/runApiTests'; import {RpcCodecs} from '../../../../common/codec/RpcCodecs'; import {RpcMessageCodecs} from '../../../../common/codec/RpcMessageCodecs'; -import {Writer} from '../../../../../util/buffers/Writer'; -import {Codecs} from '../../../../../json-pack/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {RpcMessageCodec} from '../../../../common/codec/types'; -import {JsonValueCodec} from '../../../../../json-pack/codecs/types'; +import {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import {FetchRpcClient} from '../../../../common/rpc/client/FetchRpcClient'; if (process.env.TEST_E2E) { diff --git a/src/reactive-rpc/__tests__/e2e/uws/http/StreamingRpcClient.spec.ts b/src/reactive-rpc/__tests__/e2e/uws/http/StreamingRpcClient.spec.ts index 924d564e86..ec55936d1d 100644 --- a/src/reactive-rpc/__tests__/e2e/uws/http/StreamingRpcClient.spec.ts +++ b/src/reactive-rpc/__tests__/e2e/uws/http/StreamingRpcClient.spec.ts @@ -6,10 +6,10 @@ import {ApiTestSetup, runApiTests} from '../../../../common/rpc/__tests__/runApi import {StreamingRpcClient} from '../../../../common'; import {RpcCodecs} from '../../../../common/codec/RpcCodecs'; import {RpcMessageCodecs} from '../../../../common/codec/RpcMessageCodecs'; -import {Writer} from '../../../../../util/buffers/Writer'; -import {Codecs} from '../../../../../json-pack/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {RpcMessageCodec} from '../../../../common/codec/types'; -import {JsonValueCodec} from '../../../../../json-pack/codecs/types'; +import {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; if (process.env.TEST_E2E) { const codecs = new RpcCodecs(new Codecs(new Writer()), new RpcMessageCodecs()); diff --git a/src/reactive-rpc/__tests__/e2e/uws/ws/RpcPersistentClient.spec.ts b/src/reactive-rpc/__tests__/e2e/uws/ws/RpcPersistentClient.spec.ts index 73c63d20f8..381b56665f 100644 --- a/src/reactive-rpc/__tests__/e2e/uws/ws/RpcPersistentClient.spec.ts +++ b/src/reactive-rpc/__tests__/e2e/uws/ws/RpcPersistentClient.spec.ts @@ -6,10 +6,10 @@ import {ApiTestSetup, runApiTests} from '../../../../common/rpc/__tests__/runApi import WebSocket from 'ws'; import {RpcCodecs} from '../../../../common/codec/RpcCodecs'; import {RpcMessageCodecs} from '../../../../common/codec/RpcMessageCodecs'; -import {Writer} from '../../../../../util/buffers/Writer'; -import {Codecs} from '../../../../../json-pack/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {RpcMessageCodec} from '../../../../common/codec/types'; -import {JsonValueCodec} from '../../../../../json-pack/codecs/types'; +import {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import {RpcCodec} from '../../../../common/codec/RpcCodec'; import {RpcPersistentClient, WebSocketChannel} from '../../../../common'; diff --git a/src/reactive-rpc/browser/createBinaryWsRpcClient.ts b/src/reactive-rpc/browser/createBinaryWsRpcClient.ts index dbe9cec554..457c21fc88 100644 --- a/src/reactive-rpc/browser/createBinaryWsRpcClient.ts +++ b/src/reactive-rpc/browser/createBinaryWsRpcClient.ts @@ -1,5 +1,5 @@ -import {CborJsonValueCodec} from '../../json-pack/codecs/cbor'; -import {Writer} from '../../util/buffers/Writer'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RpcPersistentClient, WebSocketChannel} from '../common'; import {RpcCodec} from '../common/codec/RpcCodec'; import {BinaryRpcMessageCodec} from '../common/codec/binary'; diff --git a/src/reactive-rpc/browser/createJsonWsRpcClient.ts b/src/reactive-rpc/browser/createJsonWsRpcClient.ts index ec8cdb07b7..d1515cbe9e 100644 --- a/src/reactive-rpc/browser/createJsonWsRpcClient.ts +++ b/src/reactive-rpc/browser/createJsonWsRpcClient.ts @@ -1,5 +1,5 @@ -import {JsonJsonValueCodec} from '../../json-pack/codecs/json'; -import {Writer} from '../../util/buffers/Writer'; +import {JsonJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/json'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RpcPersistentClient, WebSocketChannel} from '../common'; import {RpcCodec} from '../common/codec/RpcCodec'; import {CompactRpcMessageCodec} from '../common/codec/compact'; diff --git a/src/reactive-rpc/common/channel/channel.ts b/src/reactive-rpc/common/channel/channel.ts index 10690944f1..b153f6bfd8 100644 --- a/src/reactive-rpc/common/channel/channel.ts +++ b/src/reactive-rpc/common/channel/channel.ts @@ -1,6 +1,6 @@ import type {WebSocketBase, CloseEventBase} from './types'; import {Subject, ReplaySubject, BehaviorSubject, Observable, from} from 'rxjs'; -import {toUint8Array} from '../../../util/buffers/toUint8Array'; +import {toUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/toUint8Array'; import {delay, filter, map, skip, switchMap, take, takeUntil, tap} from 'rxjs/operators'; export const enum ChannelState { diff --git a/src/reactive-rpc/common/channel/mock.ts b/src/reactive-rpc/common/channel/mock.ts index f1799db9ca..ad6f978679 100644 --- a/src/reactive-rpc/common/channel/mock.ts +++ b/src/reactive-rpc/common/channel/mock.ts @@ -1,5 +1,5 @@ import {WebSocketState} from './constants'; -import {utf8Size} from '../../../util/strings/utf8'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; export interface CreateWebSocketMockParams { onClose: (code?: number, reason?: string) => void; diff --git a/src/reactive-rpc/common/codec/RpcCodec.ts b/src/reactive-rpc/common/codec/RpcCodec.ts index 7dba4e63d6..cf93a6e3a4 100644 --- a/src/reactive-rpc/common/codec/RpcCodec.ts +++ b/src/reactive-rpc/common/codec/RpcCodec.ts @@ -1,6 +1,6 @@ import type {RpcSpecifier} from '../rpc'; import type {ReactiveRpcMessage} from '../messages'; -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {RpcMessageCodec} from './types'; export class RpcCodec { diff --git a/src/reactive-rpc/common/codec/RpcCodecs.ts b/src/reactive-rpc/common/codec/RpcCodecs.ts index 9116692c02..580ebc261b 100644 --- a/src/reactive-rpc/common/codec/RpcCodecs.ts +++ b/src/reactive-rpc/common/codec/RpcCodecs.ts @@ -1,4 +1,4 @@ -import {Codecs} from '../../../json-pack/codecs/Codecs'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {RpcMessageCodecs} from './RpcMessageCodecs'; export class RpcCodecs { diff --git a/src/reactive-rpc/common/codec/binary/BinaryRpcMessageCodec.ts b/src/reactive-rpc/common/codec/binary/BinaryRpcMessageCodec.ts index 54028225a7..10485a5e04 100644 --- a/src/reactive-rpc/common/codec/binary/BinaryRpcMessageCodec.ts +++ b/src/reactive-rpc/common/codec/binary/BinaryRpcMessageCodec.ts @@ -1,9 +1,9 @@ import {RpcMessageFormat} from '../constants'; import {decode} from './decode'; import * as msg from '../../messages'; -import type {Uint8ArrayCut} from '../../../../util/buffers/Uint8ArrayCut'; +import type {Uint8ArrayCut} from '@jsonjoy.com/json-pack/lib/util/buffers/Uint8ArrayCut'; import type {RpcMessageCodec} from '../types'; -import type {JsonValueCodec} from '../../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; export class BinaryRpcMessageCodec implements RpcMessageCodec { id = 'rx.binary'; diff --git a/src/reactive-rpc/common/codec/binary/__tests__/BinaryRpcMessageCodec.spec.ts b/src/reactive-rpc/common/codec/binary/__tests__/BinaryRpcMessageCodec.spec.ts index c93c2344e7..e67bc5121e 100644 --- a/src/reactive-rpc/common/codec/binary/__tests__/BinaryRpcMessageCodec.spec.ts +++ b/src/reactive-rpc/common/codec/binary/__tests__/BinaryRpcMessageCodec.spec.ts @@ -1,5 +1,5 @@ -import {CborJsonValueCodec} from '../../../../../json-pack/codecs/cbor'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RequestCompleteMessage} from '../../../messages'; import {BinaryRpcMessageCodec} from '../BinaryRpcMessageCodec'; diff --git a/src/reactive-rpc/common/codec/binary/__tests__/automated.spec.ts b/src/reactive-rpc/common/codec/binary/__tests__/automated.spec.ts index b1c0c6bf94..49424177ad 100644 --- a/src/reactive-rpc/common/codec/binary/__tests__/automated.spec.ts +++ b/src/reactive-rpc/common/codec/binary/__tests__/automated.spec.ts @@ -1,6 +1,6 @@ import {BinaryRpcMessageCodec} from '..'; -import {CborJsonValueCodec} from '../../../../../json-pack/codecs/cbor'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {messages} from '../../../messages/__tests__/fixtures'; const codec = new BinaryRpcMessageCodec(); diff --git a/src/reactive-rpc/common/codec/binary/__tests__/decode.spec.ts b/src/reactive-rpc/common/codec/binary/__tests__/decode.spec.ts index b4cc363232..e406657c7f 100644 --- a/src/reactive-rpc/common/codec/binary/__tests__/decode.spec.ts +++ b/src/reactive-rpc/common/codec/binary/__tests__/decode.spec.ts @@ -11,10 +11,10 @@ import { } from '../../../messages'; import {RpcValue} from '../../../messages/Value'; import {decode} from '../decode'; -import {Reader} from '../../../../../util/buffers/Reader'; -import {Uint8ArrayCut} from '../../../../../util/buffers/Uint8ArrayCut'; -import {CborJsonValueCodec} from '../../../../../json-pack/codecs/cbor'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {Reader} from '@jsonjoy.com/json-pack/lib/util/buffers/Reader'; +import {Uint8ArrayCut} from '@jsonjoy.com/json-pack/lib/util/buffers/Uint8ArrayCut'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; const codec = new CborJsonValueCodec(new Writer(64)); const encoder = codec.encoder; diff --git a/src/reactive-rpc/common/codec/binary/__tests__/encode.spec.ts b/src/reactive-rpc/common/codec/binary/__tests__/encode.spec.ts index 82f9306803..789373112e 100644 --- a/src/reactive-rpc/common/codec/binary/__tests__/encode.spec.ts +++ b/src/reactive-rpc/common/codec/binary/__tests__/encode.spec.ts @@ -6,8 +6,8 @@ import { ResponseDataMessage, } from '../../../messages'; import {RpcValue} from '../../../messages/Value'; -import {CborJsonValueCodec} from '../../../../../json-pack/codecs/cbor'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; const cborCodec = new CborJsonValueCodec(new Writer(64)); const encoder = cborCodec.encoder; diff --git a/src/reactive-rpc/common/codec/binary/__tests__/smoke-tests.spec.ts b/src/reactive-rpc/common/codec/binary/__tests__/smoke-tests.spec.ts index bfcc6ab7a0..8a2f839f23 100644 --- a/src/reactive-rpc/common/codec/binary/__tests__/smoke-tests.spec.ts +++ b/src/reactive-rpc/common/codec/binary/__tests__/smoke-tests.spec.ts @@ -1,6 +1,6 @@ import {BinaryRpcMessageCodec} from '..'; -import {Writer} from '../../../../../util/buffers/Writer'; -import {Codecs} from '../../../../../json-pack/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import { NotificationMessage, ReactiveRpcMessage, diff --git a/src/reactive-rpc/common/codec/binary/decode.ts b/src/reactive-rpc/common/codec/binary/decode.ts index 8d16aab109..7c5e3b5236 100644 --- a/src/reactive-rpc/common/codec/binary/decode.ts +++ b/src/reactive-rpc/common/codec/binary/decode.ts @@ -1,4 +1,4 @@ -import {Uint8ArrayCut} from '../../../../util/buffers/Uint8ArrayCut'; +import {Uint8ArrayCut} from '@jsonjoy.com/json-pack/lib/util/buffers/Uint8ArrayCut'; import { NotificationMessage, ReactiveRpcMessage, @@ -13,7 +13,7 @@ import { } from '../../messages'; import {RpcValue} from '../../messages/Value'; import {BinaryMessageType} from './constants'; -import type {Reader} from '../../../../util/buffers/Reader'; +import type {Reader} from '@jsonjoy.com/json-pack/lib/util/buffers/Reader'; export const decode = (reader: Reader): ReactiveRpcMessage => { const word = reader.u32(); diff --git a/src/reactive-rpc/common/codec/compact/CompactRpcMessageCodec.ts b/src/reactive-rpc/common/codec/compact/CompactRpcMessageCodec.ts index fa510b0ec2..0a0c790e60 100644 --- a/src/reactive-rpc/common/codec/compact/CompactRpcMessageCodec.ts +++ b/src/reactive-rpc/common/codec/compact/CompactRpcMessageCodec.ts @@ -3,11 +3,11 @@ import {RpcError, RpcErrorCodes} from '../../rpc/caller/error'; import * as msg from '../../messages'; import {CompactMessageType} from './constants'; import {RpcValue} from '../../messages/Value'; -import {CborEncoder} from '../../../../json-pack/cbor/CborEncoder'; -import {MsgPackEncoder} from '../../../../json-pack/msgpack'; -import {JsonEncoder} from '../../../../json-pack/json/JsonEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import type {RpcMessageCodec} from '../types'; -import type {JsonValueCodec} from '../../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type * as types from './types'; const fromJson = (arr: unknown | unknown[] | types.CompactMessage): msg.ReactiveRpcMessage => { diff --git a/src/reactive-rpc/common/codec/compact/__tests__/CompactRpcMessageCodec.spec.ts b/src/reactive-rpc/common/codec/compact/__tests__/CompactRpcMessageCodec.spec.ts index f28f6ff441..c1a2450534 100644 --- a/src/reactive-rpc/common/codec/compact/__tests__/CompactRpcMessageCodec.spec.ts +++ b/src/reactive-rpc/common/codec/compact/__tests__/CompactRpcMessageCodec.spec.ts @@ -1,5 +1,5 @@ -import {MsgPackJsonValueCodec} from '../../../../../json-pack/codecs/msgpack'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {MsgPackJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/msgpack'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RequestCompleteMessage} from '../../../messages'; import {CompactRpcMessageCodec} from '../CompactRpcMessageCodec'; diff --git a/src/reactive-rpc/common/codec/compact/__tests__/automated.spec.ts b/src/reactive-rpc/common/codec/compact/__tests__/automated.spec.ts index 5e02238d7a..4be20127eb 100644 --- a/src/reactive-rpc/common/codec/compact/__tests__/automated.spec.ts +++ b/src/reactive-rpc/common/codec/compact/__tests__/automated.spec.ts @@ -1,7 +1,7 @@ import {compactMessages} from './compact-messages'; import {CompactRpcMessageCodec} from '..'; -import {CborJsonValueCodec} from '../../../../../json-pack/codecs/cbor'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {messages} from '../../../messages/__tests__/fixtures'; const codec = new CompactRpcMessageCodec(); diff --git a/src/reactive-rpc/common/codec/compact/__tests__/smoke-tests.spec.ts b/src/reactive-rpc/common/codec/compact/__tests__/smoke-tests.spec.ts index 0b1e4ef90a..bcb531186e 100644 --- a/src/reactive-rpc/common/codec/compact/__tests__/smoke-tests.spec.ts +++ b/src/reactive-rpc/common/codec/compact/__tests__/smoke-tests.spec.ts @@ -1,6 +1,6 @@ import {CompactRpcMessageCodec} from '..'; -import {Writer} from '../../../../../util/buffers/Writer'; -import {Codecs} from '../../../../../json-pack/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import { NotificationMessage, ReactiveRpcMessage, diff --git a/src/reactive-rpc/common/codec/json-rpc-2/JsonRpc2RpcMessageCodec.ts b/src/reactive-rpc/common/codec/json-rpc-2/JsonRpc2RpcMessageCodec.ts index 10bc98eaca..d5d2ab7237 100644 --- a/src/reactive-rpc/common/codec/json-rpc-2/JsonRpc2RpcMessageCodec.ts +++ b/src/reactive-rpc/common/codec/json-rpc-2/JsonRpc2RpcMessageCodec.ts @@ -1,13 +1,13 @@ import {RpcMessageFormat} from '../constants'; import {RpcError} from '../../rpc/caller/error'; import {RpcValue} from '../../messages/Value'; -import {EncodingFormat} from '../../../../json-pack/constants'; -import {TlvBinaryJsonEncoder} from '../../../../json-pack/types'; -import {JsonJsonValueCodec} from '../../../../json-pack/codecs/json'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {TlvBinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; +import {JsonJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/json'; import * as msg from '../../messages'; import * as schema from './schema'; import type {RpcMessageCodec} from '../types'; -import type {JsonValueCodec} from '../../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; export class JsonRpc2RpcMessageCodec implements RpcMessageCodec { id = 'json2.verbose'; diff --git a/src/reactive-rpc/common/codec/json-rpc-2/__tests__/automated.spec.ts b/src/reactive-rpc/common/codec/json-rpc-2/__tests__/automated.spec.ts index 4a2e536937..fd548252c5 100644 --- a/src/reactive-rpc/common/codec/json-rpc-2/__tests__/automated.spec.ts +++ b/src/reactive-rpc/common/codec/json-rpc-2/__tests__/automated.spec.ts @@ -1,6 +1,6 @@ import {JsonRpc2RpcMessageCodec} from '..'; -import {JsonJsonValueCodec} from '../../../../../json-pack/codecs/json'; -import {Writer} from '../../../../../util/buffers/Writer'; +import {JsonJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/json'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {ReactiveRpcMessage} from '../../../messages'; import {messages} from '../../../messages/__tests__/fixtures'; diff --git a/src/reactive-rpc/common/codec/types.ts b/src/reactive-rpc/common/codec/types.ts index 10b91fa9f7..543f62638b 100644 --- a/src/reactive-rpc/common/codec/types.ts +++ b/src/reactive-rpc/common/codec/types.ts @@ -1,4 +1,4 @@ -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {ReactiveRpcMessage} from '../messages'; import type {RpcMessageFormat} from './constants'; diff --git a/src/reactive-rpc/common/messages/messages.ts b/src/reactive-rpc/common/messages/messages.ts index e6af90e2ba..309e232b32 100644 --- a/src/reactive-rpc/common/messages/messages.ts +++ b/src/reactive-rpc/common/messages/messages.ts @@ -1,12 +1,12 @@ import {BinaryMessageType} from '../codec/binary/constants'; import {CompactMessageType} from '../codec/compact/constants'; import {validateId, validateMethod} from '../rpc/validation'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import {MsgPackEncoder} from '../../../json-pack/msgpack'; -import {JsonEncoder} from '../../../json-pack/json/JsonEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {MsgPackEncoder} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import type {RpcValue} from './Value'; -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; -import type {BinaryJsonEncoder} from '../../../json-pack/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; +import type {BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; import type * as cmsg from '../codec/compact/types'; import type {Message} from './types'; diff --git a/src/reactive-rpc/common/messages/types.ts b/src/reactive-rpc/common/messages/types.ts index ad460f182e..2c36fd2741 100644 --- a/src/reactive-rpc/common/messages/types.ts +++ b/src/reactive-rpc/common/messages/types.ts @@ -1,4 +1,4 @@ -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type * as msg from './messages'; /** diff --git a/src/reactive-rpc/common/rpc/__tests__/RpcPersistentClient.spec.ts b/src/reactive-rpc/common/rpc/__tests__/RpcPersistentClient.spec.ts index 3ae307e766..9eefc5dd2c 100644 --- a/src/reactive-rpc/common/rpc/__tests__/RpcPersistentClient.spec.ts +++ b/src/reactive-rpc/common/rpc/__tests__/RpcPersistentClient.spec.ts @@ -5,8 +5,8 @@ import {RequestCompleteMessage} from '../..'; import {until} from '../../../../__tests__/util'; import {RpcValue} from '../../messages/Value'; import {RpcCodec} from '../../codec/RpcCodec'; -import {Codecs} from '../../../../json-pack/codecs/Codecs'; -import {Writer} from '../../../../util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RpcMessageCodecs} from '../../codec/RpcMessageCodecs'; test('on remote method execution, sends message over WebSocket only once', async () => { diff --git a/src/reactive-rpc/common/rpc/caller/error/__tests__/RpcErrorType.spec.ts b/src/reactive-rpc/common/rpc/caller/error/__tests__/RpcErrorType.spec.ts index 3cb8b62dad..db3f7cc264 100644 --- a/src/reactive-rpc/common/rpc/caller/error/__tests__/RpcErrorType.spec.ts +++ b/src/reactive-rpc/common/rpc/caller/error/__tests__/RpcErrorType.spec.ts @@ -1,5 +1,5 @@ -import {Codecs} from '../../../../../../json-pack/codecs/Codecs'; -import {Writer} from '../../../../../../util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {RpcError} from '../RpcError'; import {RpcErrorType} from '../RpcErrorType'; diff --git a/src/reactive-rpc/common/rpc/client/EncodedStaticRpcClient.ts b/src/reactive-rpc/common/rpc/client/EncodedStaticRpcClient.ts index 04eb5feb46..3f36acae67 100644 --- a/src/reactive-rpc/common/rpc/client/EncodedStaticRpcClient.ts +++ b/src/reactive-rpc/common/rpc/client/EncodedStaticRpcClient.ts @@ -1,7 +1,7 @@ import * as msg from '../../messages'; import {StaticRpcClient} from './StaticRpcClient'; import {RpcMessageCodec} from '../../codec/types'; -import {JsonValueCodec} from '../../../../json-pack/codecs/types'; +import {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {Observable} from 'rxjs'; import type {RpcClient} from './types'; diff --git a/src/reactive-rpc/common/rpc/client/FetchRpcClient.ts b/src/reactive-rpc/common/rpc/client/FetchRpcClient.ts index 9082e6a873..eed94b78fb 100644 --- a/src/reactive-rpc/common/rpc/client/FetchRpcClient.ts +++ b/src/reactive-rpc/common/rpc/client/FetchRpcClient.ts @@ -1,7 +1,7 @@ import {StaticRpcClient, StaticRpcClientOptions} from './StaticRpcClient'; import {EncodedStaticRpcClient} from './EncodedStaticRpcClient'; import type {RpcMessageCodec} from '../../codec/types'; -import type {JsonValueCodec} from '../../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {Observable} from 'rxjs'; import type {RpcClient} from './types'; diff --git a/src/reactive-rpc/common/testing/buildE2eClient.ts b/src/reactive-rpc/common/testing/buildE2eClient.ts index 9cf624db8a..9a003f8783 100644 --- a/src/reactive-rpc/common/testing/buildE2eClient.ts +++ b/src/reactive-rpc/common/testing/buildE2eClient.ts @@ -1,6 +1,6 @@ -import {Codecs} from '../../../json-pack/codecs/Codecs'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {Fuzzer} from '../../../util/Fuzzer'; -import {Writer} from '../../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {ConnectionContext} from '../../server/context'; import {RpcCodecs} from '../codec/RpcCodecs'; import {RpcMessageCodecs} from '../codec/RpcMessageCodecs'; diff --git a/src/reactive-rpc/server/context.ts b/src/reactive-rpc/server/context.ts index d4f7a6618a..33c656c8ab 100644 --- a/src/reactive-rpc/server/context.ts +++ b/src/reactive-rpc/server/context.ts @@ -1,7 +1,7 @@ import {NullObject} from '../../util/NullObject'; -import {copy} from '../../util/buffers/copy'; -import {listToUint8} from '../../util/buffers/concat'; -import type {JsonValueCodec} from '../../json-pack/codecs/types'; +import {copy} from '@jsonjoy.com/json-pack/lib/util/buffers/copy'; +import {listToUint8} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {RpcMessageCodec} from '../common/codec/types'; import type {RpcApp} from './uws/RpcApp'; import type {HttpRequest, HttpResponse} from './uws/types'; diff --git a/src/reactive-rpc/server/http1/Http1Server.ts b/src/reactive-rpc/server/http1/Http1Server.ts index 04fca023d4..1d9a4342e1 100644 --- a/src/reactive-rpc/server/http1/Http1Server.ts +++ b/src/reactive-rpc/server/http1/Http1Server.ts @@ -1,8 +1,9 @@ import * as http from 'http'; import * as net from 'net'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; import {WsServerConnection} from '../ws/server/WsServerConnection'; import {WsFrameEncoder} from '../ws/codec/WsFrameEncoder'; -import {Writer} from '../../../util/buffers/Writer'; import {RouteMatcher} from '../../../util/router/codegen'; import {Router} from '../../../util/router'; import {Printable} from '../../../util/print/types'; @@ -11,7 +12,6 @@ import {PayloadTooLarge} from './errors'; import {findTokenInText, setCodecs} from './util'; import {Http1ConnectionContext, WsConnectionContext} from './context'; import {RpcCodecs} from '../../common/codec/RpcCodecs'; -import {Codecs} from '../../../json-pack/codecs/Codecs'; import {RpcMessageCodecs} from '../../common/codec/RpcMessageCodecs'; import {NullObject} from '../../../util/NullObject'; diff --git a/src/reactive-rpc/server/http1/context.ts b/src/reactive-rpc/server/http1/context.ts index ad1acf19e5..85e4063e3c 100644 --- a/src/reactive-rpc/server/http1/context.ts +++ b/src/reactive-rpc/server/http1/context.ts @@ -1,7 +1,7 @@ import {getBody} from './util'; -import {listToUint8} from '../../../util/buffers/concat'; +import {listToUint8} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; import type * as http from 'http'; -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; import type {RpcMessageCodec} from '../../common/codec/types'; import type {WsServerConnection} from '../ws/server/WsServerConnection'; diff --git a/src/reactive-rpc/server/uws/RpcApp.ts b/src/reactive-rpc/server/uws/RpcApp.ts index 8357dc8eb3..0aaac8af39 100644 --- a/src/reactive-rpc/server/uws/RpcApp.ts +++ b/src/reactive-rpc/server/uws/RpcApp.ts @@ -6,14 +6,14 @@ import {ConnectionContext} from '../context'; import {RpcMessageCodecs} from '../../common/codec/RpcMessageCodecs'; import {RpcValue} from '../../common/messages/Value'; import {RpcCodecs} from '../../common/codec/RpcCodecs'; -import {Codecs} from '../../../json-pack/codecs/Codecs'; -import {Writer} from '../../../util/buffers/Writer'; -import {copy} from '../../../util/buffers/copy'; +import {Codecs} from '@jsonjoy.com/json-pack/lib/codecs/Codecs'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; +import {copy} from '@jsonjoy.com/json-pack/lib/util/buffers/copy'; import {type ReactiveRpcMessage, RpcMessageStreamProcessor, ReactiveRpcClientMessage} from '../../common'; import type * as types from './types'; import type {RouteHandler} from './types'; import type {RpcCaller} from '../../common/rpc/caller/RpcCaller'; -import type {JsonValueCodec} from '../../../json-pack/codecs/types'; +import type {JsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/types'; const HDR_BAD_REQUEST = Buffer.from('400 Bad Request', 'utf8'); const HDR_NOT_FOUND = Buffer.from('404 Not Found', 'utf8'); diff --git a/src/reactive-rpc/server/ws/codec/WsFrameDecoder.ts b/src/reactive-rpc/server/ws/codec/WsFrameDecoder.ts index e9bedbf767..7025a4485d 100644 --- a/src/reactive-rpc/server/ws/codec/WsFrameDecoder.ts +++ b/src/reactive-rpc/server/ws/codec/WsFrameDecoder.ts @@ -1,4 +1,4 @@ -import {StreamingOctetReader} from '../../../../util/buffers/StreamingOctetReader'; +import {StreamingOctetReader} from '@jsonjoy.com/json-pack/lib/util/buffers/StreamingOctetReader'; import {WsFrameOpcode} from './constants'; import {WsFrameDecodingError} from './errors'; import {WsCloseFrame, WsFrameHeader, WsPingFrame, WsPongFrame} from './frames'; diff --git a/src/reactive-rpc/server/ws/codec/WsFrameEncoder.ts b/src/reactive-rpc/server/ws/codec/WsFrameEncoder.ts index b706d1acf0..f92ddbbc4a 100644 --- a/src/reactive-rpc/server/ws/codec/WsFrameEncoder.ts +++ b/src/reactive-rpc/server/ws/codec/WsFrameEncoder.ts @@ -1,7 +1,7 @@ -import {Writer} from '../../../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {WsFrameOpcode} from './constants'; -import type {IWriter, IWriterGrowable} from '../../../../util/buffers'; import {WsFrameEncodingError} from './errors'; +import type {IWriter, IWriterGrowable} from '@jsonjoy.com/json-pack/lib/util/buffers'; const maskBuf = new Uint8Array(4); const maskBufView = new DataView(maskBuf.buffer, maskBuf.byteOffset, maskBuf.byteLength); diff --git a/src/reactive-rpc/server/ws/server/WsServerConnection.ts b/src/reactive-rpc/server/ws/server/WsServerConnection.ts index cdd092136e..0919f0487c 100644 --- a/src/reactive-rpc/server/ws/server/WsServerConnection.ts +++ b/src/reactive-rpc/server/ws/server/WsServerConnection.ts @@ -1,8 +1,8 @@ import * as crypto from 'crypto'; import * as stream from 'stream'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; +import {listToUint8} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; import {WsCloseFrame, WsFrameDecoder, WsFrameHeader, WsFrameOpcode, WsPingFrame, WsPongFrame} from '../codec'; -import {utf8Size} from '../../../../util/strings/utf8'; -import {listToUint8} from '../../../../util/buffers/concat'; import type {WsFrameEncoder} from '../codec/WsFrameEncoder'; export type WsServerConnectionSocket = stream.Duplex; diff --git a/src/reactive-rpc/server/ws/server/__tests__/WsServerConnection.spec.ts b/src/reactive-rpc/server/ws/server/__tests__/WsServerConnection.spec.ts index 4b50147b73..e6aeee348e 100644 --- a/src/reactive-rpc/server/ws/server/__tests__/WsServerConnection.spec.ts +++ b/src/reactive-rpc/server/ws/server/__tests__/WsServerConnection.spec.ts @@ -3,8 +3,8 @@ import {WsServerConnection} from '../WsServerConnection'; import {WsFrameEncoder} from '../../codec/WsFrameEncoder'; import {until} from 'thingies'; import {WsFrameOpcode} from '../../codec'; -import {bufferToUint8Array} from '../../../../../util/buffers/bufferToUint8Array'; -import {listToUint8} from '../../../../../util/buffers/concat'; +import {bufferToUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/bufferToUint8Array'; +import {listToUint8} from '@jsonjoy.com/json-pack/lib/util/buffers/concat'; const setup = () => { const socket = new stream.PassThrough(); diff --git a/src/util/base64/README.md b/src/util/base64/README.md deleted file mode 100644 index ba368cec0a..0000000000 --- a/src/util/base64/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# Base64 - - -## Encoder - -- Implements Base64 encoding algorithm compatible with Node's Buffer. -- Isomorphic—it can be used in, both, Node and the browser. -- Faster than the Node's implementation for short blobs, smaller than 40 bytes. -- Uses Node's implementation for long blobs, if available. Hence, it also works - in browser, but in Node environment will perform faster for short strings. - - -### Usage - -Use encoder compatible with Node's Buffer: - -```ts -import {toBase64} from 'json-joy/lib/util/base64'; - -toBase64(new Uint8Array([1, 2, 3])); -``` - -Create your custom encoder: - -```ts -import {createToBase64} from 'json-joy/lib/util/base64'; - -const encode = createToBase64('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_'); - -encode(new Uint8Array([1, 2, 3])); -``` - - -### Benchmark - -Below benchmark encodes random binary blobs of sizes 8, 16, 32, 64, 128, 256, 512, and 1024 byes. -`json-joy/util/base64` is faster, because for short strings (less than 40 chars) it uses a -native JavaScript implementation, which is faster and also works in browsers. For blobs larger -than 40 chars, it falls back to Node `Buffer` implementation, if available. - -Encoding: - -``` -node benchmarks/util/base64/encode.js -json-joy/util/base64 toBase64(uint8) x 1,257,419 ops/sec ±1.19% (93 runs sampled), 795 ns/op -json-joy/util/base64 createToBase64()(uint8) x 868,953 ops/sec ±0.96% (96 runs sampled), 1151 ns/op -js-base64 x 974,991 ops/sec ±0.73% (94 runs sampled), 1026 ns/op -fast-base64-encode x 428,545 ops/sec ±1.67% (96 runs sampled), 2333 ns/op -base64-js x 295,165 ops/sec ±1.59% (98 runs sampled), 3388 ns/op -Buffer.from(uint8).toString('base64'); x 973,173 ops/sec ±0.65% (95 runs sampled), 1028 ns/op -Fastest is json-joy/util/base64 toBase64(uint8) -``` - -Decoding: - -``` -node benchmarks/util/base64/decode.js -json-joy/util/base64 fromBase64(str) x 602,268 ops/sec ±1.09% (88 runs sampled), 1660 ns/op -json-joy/util/base64 createFromBase64()(str) x 392,345 ops/sec ±0.96% (91 runs sampled), 2549 ns/op -Buffer.from(str, 'base64') x 498,609 ops/sec ±1.66% (93 runs sampled), 2006 ns/op -base64-js x 439,246 ops/sec ±0.94% (89 runs sampled), 2277 ns/op -js-base64 x 151,694 ops/sec ±0.51% (99 runs sampled), 6592 ns/op -Fastest is json-joy/util/base64 fromBase64(str) -``` - - -## Decoder - -- Uses Node.js built-in `Buffer`, if available. -- When `Buffer` is not available, uses JavaScript implementation. - - -### Usage - -Use decoder compatible with Node's Buffer: - -```ts -import {toBase64, fromBase64} from 'json-joy/lib/util/base64'; - -fromBase64(toBase64(new Uint8Array([1, 2, 3]))); -``` - -Create your custom encoder: - -```ts -import {createFromBase64} from 'json-joy/lib/util/base64'; - -const decoder = createFromBase64('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_'); - -decoder(toBase64(new Uint8Array([1, 2, 3]))); -``` diff --git a/src/util/base64/__bench__/decode.js b/src/util/base64/__bench__/decode.js deleted file mode 100644 index 9b6de6dfa0..0000000000 --- a/src/util/base64/__bench__/decode.js +++ /dev/null @@ -1,77 +0,0 @@ -const Benchmark = require('benchmark'); -const toBase64 = require('../../../../lib/util/base64').toBase64; -const {bufferToUint8Array} = require('../../../../lib/util/buffers/bufferToUint8Array'); -const {fromBase64, createFromBase64} = require('../../../../lib/util/base64'); -const {toByteArray} = require('base64-js'); -const {decode: decodeJsBase64} = require('js-base64'); - -const fromBase642 = createFromBase64(); - -const generateBlob = (length) => { - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -const str4 = toBase64(generateBlob(4)); -const str8 = toBase64(generateBlob(8)); -const str16 = toBase64(generateBlob(16)); -const str24 = toBase64(generateBlob(24)); -const str32 = toBase64(generateBlob(32)); -const str64 = toBase64(generateBlob(64)); -const str128 = toBase64(generateBlob(128)); -const str256 = toBase64(generateBlob(256)); - -const suite = new Benchmark.Suite(); - -const encoders = [ - { - name: `json-joy/util/base64 fromBase64(str)`, - decode: (str) => fromBase64(str), - }, - { - name: `json-joy/util/base64 createFromBase64()(str)`, - decode: (str) => fromBase642(str), - }, - { - name: `Buffer.from(str, 'base64')`, - decode: (str) => bufferToUint8Array(Buffer.from(str, 'base64')), - }, - { - name: `base64-js`, - decode: (str) => toByteArray(str), - }, - { - name: `js-base64`, - decode: (str) => decodeJsBase64(str), - }, -]; - -for (const encoder of encoders) { - // Warm up - for (let i = 0; i < 100000; i++) { - encoder.decode(str8); - encoder.decode(str256); - } - suite.add(encoder.name, () => { - encoder.decode(str4); - encoder.decode(str8); - encoder.decode(str16); - encoder.decode(str24); - encoder.decode(str32); - encoder.decode(str64); - encoder.decode(str128); - encoder.decode(str256); - }); -} - -suite - .on('cycle', function (event) { - console.log(String(event.target) + `, ${Math.round(1000000000 / event.target.hz)} ns/op`); - }) - .on('complete', function () { - console.log('Fastest is ' + this.filter('fastest').map('name')); - }) - .run(); diff --git a/src/util/base64/__bench__/encode.js b/src/util/base64/__bench__/encode.js deleted file mode 100644 index 07fbd4edde..0000000000 --- a/src/util/base64/__bench__/encode.js +++ /dev/null @@ -1,98 +0,0 @@ -const Benchmark = require('benchmark'); -const {toBase64, createToBase64} = require('../../../../lib/util/base64'); -const {fromByteArray} = require('base64-js'); -const {encode: encodeJsBase64} = require('js-base64'); - -const toBase64Native = createToBase64(); - -const generateBlob = (length) => { - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -const arr8 = generateBlob(9); -const arr16 = generateBlob(17); -const arr32 = generateBlob(33); -const arr64 = generateBlob(65); -const arr128 = generateBlob(127); -const arr256 = generateBlob(257); -const arr512 = generateBlob(513); -const arr1024 = generateBlob(1025); - -// fast-base64-encode -const table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); -const fastBase64Encode = (source) => { - let out = ''; - let tmp; - const length = source.byteLength; - const extraLength = length % 3; - const baseLength = length - extraLength; - for (let i = 0; i < baseLength; i += 3) { - tmp = ((source[i] & 0xff) << 16) | ((source[i + 1] & 0xff) << 8) | (source[i + 2] & 0xff); - out += table[(tmp >> 18) & 0x3f] + table[(tmp >> 12) & 0x3f] + table[(tmp >> 6) & 0x3f] + table[tmp & 0x3f]; - } - if (extraLength) { - if (extraLength === 1) { - tmp = source[baseLength] & 0xff; - out += table[tmp >> 2] + table[(tmp << 4) & 0x3f] + '=='; - } else { - tmp = ((source[baseLength] & 0xff) << 8) | (source[baseLength + 1] & 0xff); - out += table[tmp >> 10] + table[(tmp >> 4) & 0x3f] + table[(tmp << 2) & 0x3f] + '='; - } - } - return out; -}; - -const suite = new Benchmark.Suite(); - -const encoders = [ - { - name: `json-joy/util/base64 toBase64(uint8)`, - encode: (uint8) => toBase64(uint8), - }, - { - name: `json-joy/util/base64 createToBase64()(uint8)`, - encode: (uint8) => toBase64Native(uint8, uint8.length), - }, - { - name: `js-base64`, - encode: (uint8) => encodeJsBase64(uint8), - }, - { - name: `fast-base64-encode`, - encode: (uint8) => fastBase64Encode(uint8), - }, - { - name: `base64-js`, - encode: (uint8) => fromByteArray(uint8), - }, - { - name: `Buffer.from(uint8).toString('base64');`, - encode: (uint8) => Buffer.from(uint8).toString('base64'), - }, -]; - -for (const encoder of encoders) { - suite.add(encoder.name, () => { - encoder.encode(arr8); - encoder.encode(arr16); - encoder.encode(arr32); - encoder.encode(arr64); - encoder.encode(arr128); - // encoder.encode(arr256); - // encoder.encode(arr512); - // encoder.encode(arr1024); - }); -} - -suite - .on('cycle', function (event) { - console.log(String(event.target) + `, ${Math.round(1000000000 / event.target.hz)} ns/op`); - }) - .on('complete', function () { - console.log('Fastest is ' + this.filter('fastest').map('name')); - }) - .run(); diff --git a/src/util/base64/__tests__/decode-base64url.spec.ts b/src/util/base64/__tests__/decode-base64url.spec.ts deleted file mode 100644 index 3344250fc3..0000000000 --- a/src/util/base64/__tests__/decode-base64url.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {toBase64} from '../toBase64'; -import {fromBase64Url} from '../fromBase64Url'; - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100); - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const encoded = toBase64(blob).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); - const decoded2 = fromBase64Url(encoded); - expect(decoded2).toEqual(blob); - } -}); diff --git a/src/util/base64/__tests__/decode-bin.spec.ts b/src/util/base64/__tests__/decode-bin.spec.ts deleted file mode 100644 index ba0c5ffba9..0000000000 --- a/src/util/base64/__tests__/decode-bin.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {toBase64Bin} from '../toBase64Bin'; -import {fromBase64Bin} from '../fromBase64Bin'; - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100); - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const dest = new Uint8Array(blob.length * 4); - const length = toBase64Bin(blob, 0, blob.length, new DataView(dest.buffer), 0); - const encoded = dest.subarray(0, length); - const view = new DataView(encoded.buffer); - const decoded = fromBase64Bin(view, 0, encoded.length); - let padding = 0; - if (encoded.length > 0 && view.getUint8(encoded.length - 1) === 0x3d) padding++; - if (encoded.length > 1 && view.getUint8(encoded.length - 2) === 0x3d) padding++; - const decoded2 = fromBase64Bin(view, 0, encoded.length - padding); - // console.log('blob', blob); - // console.log('encoded', encoded); - // console.log('decoded', decoded); - expect(decoded).toEqual(blob); - expect(decoded2).toEqual(blob); - } -}); diff --git a/src/util/base64/__tests__/decode.spec.ts b/src/util/base64/__tests__/decode.spec.ts deleted file mode 100644 index 273857a466..0000000000 --- a/src/util/base64/__tests__/decode.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {toBase64} from '../toBase64'; -import {fromBase64} from '../fromBase64'; -import {createFromBase64} from '../createFromBase64'; - -const fromBase64_2 = createFromBase64(); - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100); - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const encoded = toBase64(blob); - const decoded1 = fromBase64_2(encoded); - const decoded2 = fromBase64(encoded); - expect(decoded1).toEqual(blob); - expect(decoded2).toEqual(blob); - } -}); - -test('handles invalid values', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const encoded = toBase64(blob); - expect(() => fromBase64_2(encoded + '!!!!')).toThrowError(new Error('INVALID_BASE64_STRING')); - } -}); diff --git a/src/util/base64/__tests__/encode-base64url.spec.ts b/src/util/base64/__tests__/encode-base64url.spec.ts deleted file mode 100644 index 1d2880f21b..0000000000 --- a/src/util/base64/__tests__/encode-base64url.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {toBase64Url} from '../toBase64Url'; - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100) + 1; - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const expected = Buffer.from(blob).toString('base64'); - const base64url = toBase64Url(blob, blob.length); - let encoded = base64url.replace(/-/g, '+').replace(/_/g, '/'); - const mod = encoded.length % 4; - if (mod === 2) encoded += '=='; - else if (mod === 3) encoded += '='; - expect(encoded).toEqual(expected); - } -}); diff --git a/src/util/base64/__tests__/encode-bin.spec.ts b/src/util/base64/__tests__/encode-bin.spec.ts deleted file mode 100644 index 6ce22c6bdd..0000000000 --- a/src/util/base64/__tests__/encode-bin.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {toBase64} from '../toBase64'; -import {createToBase64Bin} from '../createToBase64Bin'; -import {createToBase64BinUint8} from '../createToBase64BinUint8'; -import {bufferToUint8Array} from '../../buffers/bufferToUint8Array'; -import {copy} from '../../buffers/copy'; - -const encode = createToBase64Bin('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '='); -const encodeUint8 = createToBase64BinUint8('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', '='); -const encodeNoPadding = createToBase64Bin('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'); - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100) + 1; - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const result = bufferToUint8Array(Buffer.from(toBase64(blob))); - const binWithBuffer = new Uint8Array(result.length + 3); - encode(blob, 0, blob.length, new DataView(binWithBuffer.buffer), 3); - const dupe = copy(blob); - encodeNoPadding(blob, 0, blob.length, new DataView(binWithBuffer.buffer), 3); - expect(dupe).toEqual(blob); - const dupe2 = copy(blob); - encodeUint8(blob, 0, blob.length, binWithBuffer, 3); - expect(dupe2).toEqual(blob); - const encoded = binWithBuffer.subarray(3); - // console.log(result); - // console.log(binWithBuffer); - // console.log(encoded); - expect(result).toEqual(encoded); - } -}); diff --git a/src/util/base64/__tests__/encode.spec.ts b/src/util/base64/__tests__/encode.spec.ts deleted file mode 100644 index 74a4c6231b..0000000000 --- a/src/util/base64/__tests__/encode.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {toBase64} from '../toBase64'; -import {createToBase64} from '../createToBase64'; - -const encode2 = createToBase64(); - -const generateBlob = (): Uint8Array => { - const length = Math.floor(Math.random() * 100) + 1; - const uint8 = new Uint8Array(length); - for (let i = 0; i < length; i++) { - uint8[i] = Math.floor(Math.random() * 256); - } - return uint8; -}; - -test('works', () => { - for (let i = 0; i < 100; i++) { - const blob = generateBlob(); - const result = toBase64(blob); - const result2 = encode2(blob, blob.byteLength); - const expected = Buffer.from(blob).toString('base64'); - expect(result).toBe(expected); - expect(result2).toBe(expected); - } -}); diff --git a/src/util/base64/constants.ts b/src/util/base64/constants.ts deleted file mode 100644 index 46b1926330..0000000000 --- a/src/util/base64/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; -export const hasBuffer = typeof Buffer === 'function' && typeof Buffer.from === 'function'; diff --git a/src/util/base64/createFromBase64.ts b/src/util/base64/createFromBase64.ts deleted file mode 100644 index 5f4922f4e4..0000000000 --- a/src/util/base64/createFromBase64.ts +++ /dev/null @@ -1,66 +0,0 @@ -import {alphabet} from './constants'; - -const E = '='; - -export const createFromBase64 = (chars: string = alphabet, noPadding: boolean = false) => { - if (chars.length !== 64) throw new Error('chars must be 64 characters long'); - let max = 0; - for (let i = 0; i < chars.length; i++) max = Math.max(max, chars.charCodeAt(i)); - const table: number[] = []; - for (let i = 0; i <= max; i += 1) table[i] = -1; - for (let i = 0; i < chars.length; i++) table[chars.charCodeAt(i)] = i; - - return (encoded: string): Uint8Array => { - if (!encoded) return new Uint8Array(0); - let length = encoded.length; - if (noPadding) { - const mod = length % 4; - if (mod === 2) { - encoded += '=='; - length += 2; - } else if (mod === 3) { - encoded += '='; - length += 1; - } - } - if (length % 4 !== 0) throw new Error('Base64 string length must be a multiple of 4'); - const mainLength = encoded[length - 1] !== E ? length : length - 4; - let bufferLength = (length >> 2) * 3; - let padding = 0; - if (encoded[length - 2] === E) { - padding = 2; - bufferLength -= 2; - } else if (encoded[length - 1] === E) { - padding = 1; - bufferLength -= 1; - } - const buf = new Uint8Array(bufferLength); - let j = 0; - let i = 0; - for (; i < mainLength; i += 4) { - const sextet0 = table[encoded.charCodeAt(i)]; - const sextet1 = table[encoded.charCodeAt(i + 1)]; - const sextet2 = table[encoded.charCodeAt(i + 2)]; - const sextet3 = table[encoded.charCodeAt(i + 3)]; - if (sextet0 < 0 || sextet1 < 0 || sextet2 < 0 || sextet3 < 0) throw new Error('INVALID_BASE64_STRING'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2); - buf[j + 2] = (sextet2 << 6) | sextet3; - j += 3; - } - if (padding === 2) { - const sextet0 = table[encoded.charCodeAt(mainLength)]; - const sextet1 = table[encoded.charCodeAt(mainLength + 1)]; - if (sextet0 < 0 || sextet1 < 0) throw new Error('INVALID_BASE64_STRING'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - } else if (padding === 1) { - const sextet0 = table[encoded.charCodeAt(mainLength)]; - const sextet1 = table[encoded.charCodeAt(mainLength + 1)]; - const sextet2 = table[encoded.charCodeAt(mainLength + 2)]; - if (sextet0 < 0 || sextet1 < 0 || sextet2 < 0) throw new Error('INVALID_BASE64_STRING'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2); - } - return buf; - }; -}; diff --git a/src/util/base64/createFromBase64Bin.ts b/src/util/base64/createFromBase64Bin.ts deleted file mode 100644 index ed9b018cb9..0000000000 --- a/src/util/base64/createFromBase64Bin.ts +++ /dev/null @@ -1,73 +0,0 @@ -import {alphabet} from './constants'; - -export const createFromBase64Bin = (chars: string = alphabet, pad: string = '=') => { - if (chars.length !== 64) throw new Error('chars must be 64 characters long'); - let max = 0; - for (let i = 0; i < chars.length; i++) max = Math.max(max, chars.charCodeAt(i)); - const table: number[] = []; - for (let i = 0; i <= max; i += 1) table[i] = -1; - for (let i = 0; i < chars.length; i++) table[chars.charCodeAt(i)] = i; - - const doExpectPadding = pad.length === 1; - const PAD = doExpectPadding ? pad.charCodeAt(0) : 0; - - return (view: DataView, offset: number, length: number): Uint8Array => { - if (!length) return new Uint8Array(0); - let padding = 0; - if (length % 4 !== 0) { - padding = 4 - (length % 4); - length += padding; - } else { - const end = offset + length; - const last = end - 1; - if (view.getUint8(last) === PAD) { - padding = 1; - if (length > 1 && view.getUint8(last - 1) === PAD) padding = 2; - } - } - if (length % 4 !== 0) throw new Error('Base64 string length must be a multiple of 4'); - const mainEnd = offset + length - (padding ? 4 : 0); - const bufferLength = (length >> 2) * 3 - padding; - const buf = new Uint8Array(bufferLength); - let j = 0; - let i = offset; - for (; i < mainEnd; i += 4) { - const word = view.getUint32(i); - const octet0 = word >>> 24; - const octet1 = (word >>> 16) & 0xff; - const octet2 = (word >>> 8) & 0xff; - const octet3 = word & 0xff; - const sextet0 = table[octet0]; - const sextet1 = table[octet1]; - const sextet2 = table[octet2]; - const sextet3 = table[octet3]; - if (sextet0 < 0 || sextet1 < 0 || sextet2 < 0 || sextet3 < 0) throw new Error('INVALID_BASE64_SEQ'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2); - buf[j + 2] = (sextet2 << 6) | sextet3; - j += 3; - } - if (!padding) return buf; - if (padding === 1) { - const word = view.getUint16(mainEnd); - const octet0 = word >> 8; - const octet1 = word & 0xff; - const octet2 = view.getUint8(mainEnd + 2); - const sextet0 = table[octet0]; - const sextet1 = table[octet1]; - const sextet2 = table[octet2]; - if (sextet0 < 0 || sextet1 < 0 || sextet2 < 0) throw new Error('INVALID_BASE64_SEQ'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - buf[j + 1] = (sextet1 << 4) | (sextet2 >> 2); - return buf; - } - const word = view.getUint16(mainEnd); - const octet0 = word >> 8; - const octet1 = word & 0xff; - const sextet0 = table[octet0]; - const sextet1 = table[octet1]; - if (sextet0 < 0 || sextet1 < 0) throw new Error('INVALID_BASE64_SEQ'); - buf[j] = (sextet0 << 2) | (sextet1 >> 4); - return buf; - }; -}; diff --git a/src/util/base64/createToBase64.ts b/src/util/base64/createToBase64.ts deleted file mode 100644 index 83681524b4..0000000000 --- a/src/util/base64/createToBase64.ts +++ /dev/null @@ -1,45 +0,0 @@ -import {flatstr} from '../strings/flatstr'; -import {alphabet} from './constants'; - -export const createToBase64 = (chars: string = alphabet, pad: string = '=') => { - if (chars.length !== 64) throw new Error('chars must be 64 characters long'); - - const table = chars.split(''); - const table2: string[] = []; - - for (const c1 of table) { - for (const c2 of table) { - const two = flatstr(c1 + c2); - table2.push(two); - } - } - - const E: string = pad; - const EE: string = flatstr(pad + pad); - - return (uint8: Uint8Array, length: number): string => { - let out = ''; - const extraLength = length % 3; - const baseLength = length - extraLength; - for (let i = 0; i < baseLength; i += 3) { - const o1 = uint8[i]; - const o2 = uint8[i + 1]; - const o3 = uint8[i + 2]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = ((o2 & 0b1111) << 8) | o3; - out += table2[v1] + table2[v2]; - } - if (!extraLength) return out; - if (extraLength === 1) { - const o1 = uint8[baseLength]; - out += table2[o1 << 4] + EE; - } else { - const o1 = uint8[baseLength]; - const o2 = uint8[baseLength + 1]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = (o2 & 0b1111) << 2; - out += table2[v1] + table[v2] + E; - } - return out; - }; -}; diff --git a/src/util/base64/createToBase64Bin.ts b/src/util/base64/createToBase64Bin.ts deleted file mode 100644 index 95e3a92758..0000000000 --- a/src/util/base64/createToBase64Bin.ts +++ /dev/null @@ -1,58 +0,0 @@ -import {alphabet} from './constants'; - -export const createToBase64Bin = (chars: string = alphabet, pad: string = '=') => { - if (chars.length !== 64) throw new Error('chars must be 64 characters long'); - - const table = chars.split('').map((c) => c.charCodeAt(0)); - const table2: number[] = []; - - for (const c1 of table) { - for (const c2 of table) { - const two = (c1 << 8) + c2; - table2.push(two); - } - } - - const doAddPadding = pad.length === 1; - const E: number = doAddPadding ? pad.charCodeAt(0) : 0; - const EE: number = doAddPadding ? (E << 8) | E : 0; - - return (uint8: Uint8Array, start: number, length: number, dest: DataView, offset: number): number => { - const extraLength = length % 3; - const baseLength = length - extraLength; - for (; start < baseLength; start += 3) { - const o1 = uint8[start]; - const o2 = uint8[start + 1]; - const o3 = uint8[start + 2]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = ((o2 & 0b1111) << 8) | o3; - dest.setInt32(offset, (table2[v1] << 16) + table2[v2]); - offset += 4; - } - if (extraLength === 1) { - const o1 = uint8[baseLength]; - if (doAddPadding) { - dest.setInt32(offset, (table2[o1 << 4] << 16) + EE); - offset += 4; - } else { - dest.setInt16(offset, table2[o1 << 4]); - offset += 2; - } - } else if (extraLength) { - const o1 = uint8[baseLength]; - const o2 = uint8[baseLength + 1]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = (o2 & 0b1111) << 2; - if (doAddPadding) { - dest.setInt32(offset, (table2[v1] << 16) + (table[v2] << 8) + E); - offset += 4; - } else { - dest.setInt16(offset, table2[v1]); - offset += 2; - dest.setInt8(offset, table[v2]); - offset += 1; - } - } - return offset; - }; -}; diff --git a/src/util/base64/createToBase64BinUint8.ts b/src/util/base64/createToBase64BinUint8.ts deleted file mode 100644 index efa77615b0..0000000000 --- a/src/util/base64/createToBase64BinUint8.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {alphabet} from './constants'; - -export const createToBase64BinUint8 = (chars: string = alphabet, pad: string = '=') => { - if (chars.length !== 64) throw new Error('chars must be 64 characters long'); - - const table = chars.split('').map((c) => c.charCodeAt(0)); - const table2: number[] = []; - - for (const c1 of table) { - for (const c2 of table) { - const two = (c1 << 8) + c2; - table2.push(two); - } - } - - const PAD: number = pad.length === 1 ? pad.charCodeAt(0) : 0; - - return (uint8: Uint8Array, start: number, length: number, dest: Uint8Array, offset: number): number => { - const extraLength = length % 3; - const baseLength = length - extraLength; - for (; start < baseLength; start += 3) { - const o1 = uint8[start]; - const o2 = uint8[start + 1]; - const o3 = uint8[start + 2]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = ((o2 & 0b1111) << 8) | o3; - let u16 = table2[v1]; - dest[offset++] = u16 >> 8; - dest[offset++] = u16; - u16 = table2[v2]; - dest[offset++] = u16 >> 8; - dest[offset++] = u16; - } - if (extraLength === 1) { - const o1 = uint8[baseLength]; - const u16 = table2[o1 << 4]; - dest[offset++] = u16 >> 8; - dest[offset++] = u16; - if (PAD) { - dest[offset++] = PAD; - dest[offset++] = PAD; - } - } else if (extraLength) { - const o1 = uint8[baseLength]; - const o2 = uint8[baseLength + 1]; - const v1 = (o1 << 4) | (o2 >> 4); - const v2 = (o2 & 0b1111) << 2; - const u16 = table2[v1]; - dest[offset++] = u16 >> 8; - dest[offset++] = u16; - dest[offset++] = table[v2]; - if (PAD) dest[offset++] = PAD; - } - return offset; - }; -}; diff --git a/src/util/base64/fromBase64.ts b/src/util/base64/fromBase64.ts deleted file mode 100644 index f9a6bb8c7e..0000000000 --- a/src/util/base64/fromBase64.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {bufferToUint8Array} from '../buffers/bufferToUint8Array'; -import {hasBuffer} from './constants'; -import {createFromBase64} from './createFromBase64'; - -const fromBase64Cpp = hasBuffer ? (encoded: string) => bufferToUint8Array(Buffer.from(encoded, 'base64')) : null; -const fromBase64Native = createFromBase64(); - -export const fromBase64 = !fromBase64Cpp - ? fromBase64Native - : (encoded: string): Uint8Array => (encoded.length > 48 ? fromBase64Cpp(encoded) : fromBase64Native(encoded)); diff --git a/src/util/base64/fromBase64Bin.ts b/src/util/base64/fromBase64Bin.ts deleted file mode 100644 index 678898d5ed..0000000000 --- a/src/util/base64/fromBase64Bin.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {createFromBase64Bin} from './createFromBase64Bin'; - -export const fromBase64Bin = createFromBase64Bin(); diff --git a/src/util/base64/fromBase64Url.ts b/src/util/base64/fromBase64Url.ts deleted file mode 100644 index 12be59f819..0000000000 --- a/src/util/base64/fromBase64Url.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {createFromBase64} from './createFromBase64'; - -export const fromBase64Url = createFromBase64('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', true); diff --git a/src/util/base64/index.ts b/src/util/base64/index.ts deleted file mode 100644 index 0c865ce8c8..0000000000 --- a/src/util/base64/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './createToBase64'; -export * from './createToBase64Bin'; -export * from './createFromBase64'; -export * from './toBase64'; -export * from './toBase64Bin'; -export * from './fromBase64'; -export * from './fromBase64Bin'; diff --git a/src/util/base64/toBase64.ts b/src/util/base64/toBase64.ts deleted file mode 100644 index be2688b3e2..0000000000 --- a/src/util/base64/toBase64.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {hasBuffer} from './constants'; -import {createToBase64} from './createToBase64'; - -const encodeSmall = createToBase64(); - -export const toBase64 = !hasBuffer - ? (uint8: Uint8Array) => encodeSmall(uint8, uint8.length) - : (uint8: Uint8Array): string => { - const length = uint8.length; - if (length <= 48) return encodeSmall(uint8, length); - return Buffer.from(uint8).toString('base64'); - }; diff --git a/src/util/base64/toBase64Bin.ts b/src/util/base64/toBase64Bin.ts deleted file mode 100644 index 012f2c24a9..0000000000 --- a/src/util/base64/toBase64Bin.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {createToBase64Bin} from './createToBase64Bin'; - -export const toBase64Bin = createToBase64Bin(); diff --git a/src/util/base64/toBase64Url.ts b/src/util/base64/toBase64Url.ts deleted file mode 100644 index 4188ca42d0..0000000000 --- a/src/util/base64/toBase64Url.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {createToBase64} from './createToBase64'; - -export const toBase64Url = createToBase64('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_', ''); diff --git a/src/util/buffers/Reader.ts b/src/util/buffers/Reader.ts deleted file mode 100644 index 160e9cdc83..0000000000 --- a/src/util/buffers/Reader.ts +++ /dev/null @@ -1,105 +0,0 @@ -import {decodeUtf8} from './utf8/decodeUtf8'; -import type {IReader, IReaderResettable} from './types'; - -export class Reader implements IReader, IReaderResettable { - public uint8 = new Uint8Array([]); - public view = new DataView(this.uint8.buffer); - public x = 0; - - public reset(uint8: Uint8Array): void { - this.x = 0; - this.uint8 = uint8; - this.view = new DataView(uint8.buffer, uint8.byteOffset, uint8.length); - } - - public peak(): number { - return this.view.getUint8(this.x); - } - - public skip(length: number): void { - this.x += length; - } - - public buf(size: number): Uint8Array { - const end = this.x + size; - const bin = this.uint8.subarray(this.x, end); - this.x = end; - return bin; - } - - public u8(): number { - return this.uint8[this.x++]; - // return this.view.getUint8(this.x++); - } - - public i8(): number { - return this.view.getInt8(this.x++); - } - - public u16(): number { - // const num = this.view.getUint16(this.x); - // this.x += 2; - // return num; - let x = this.x; - const num = (this.uint8[x++] << 8) + this.uint8[x++]; - this.x = x; - return num; - } - - public i16(): number { - const num = this.view.getInt16(this.x); - this.x += 2; - return num; - } - - public u32(): number { - const num = this.view.getUint32(this.x); - this.x += 4; - return num; - } - - public i32(): number { - const num = this.view.getInt32(this.x); - this.x += 4; - return num; - } - - public u64(): bigint { - const num = this.view.getBigUint64(this.x); - this.x += 8; - return num; - } - - public i64(): bigint { - const num = this.view.getBigInt64(this.x); - this.x += 8; - return num; - } - - public f32(): number { - const pos = this.x; - this.x += 4; - return this.view.getFloat32(pos); - } - - public f64(): number { - const pos = this.x; - this.x += 8; - return this.view.getFloat64(pos); - } - - public utf8(size: number): string { - const start = this.x; - this.x += size; - return decodeUtf8(this.uint8, start, size); - } - - public ascii(length: number): string { - const uint8 = this.uint8; - let str = ''; - const end = this.x + length; - for (let i = this.x; i < end; i++) str += String.fromCharCode(uint8[i]); - this.x = end; - return str; - } -} diff --git a/src/util/buffers/Slice.ts b/src/util/buffers/Slice.ts deleted file mode 100644 index c0287b831f..0000000000 --- a/src/util/buffers/Slice.ts +++ /dev/null @@ -1,12 +0,0 @@ -export class Slice { - constructor( - public readonly uint8: Uint8Array, - public readonly view: DataView, - public readonly start: number, - public readonly end: number, - ) {} - - public subarray(): Uint8Array { - return this.uint8.subarray(this.start, this.end); - } -} diff --git a/src/util/buffers/StreamingOctetReader.ts b/src/util/buffers/StreamingOctetReader.ts deleted file mode 100644 index b254a75647..0000000000 --- a/src/util/buffers/StreamingOctetReader.ts +++ /dev/null @@ -1,175 +0,0 @@ -const fromCharCode = String.fromCharCode; - -export class StreamingOctetReader { - protected readonly chunks: Uint8Array[] = []; - - /** Total size of all chunks. */ - protected chunkSize: number = 0; - - protected x: number = 0; - - public size(): number { - return this.chunkSize - this.x; - } - - public push(chunk: Uint8Array): void { - this.chunks.push(chunk); - this.chunkSize += chunk.length; - } - - protected assertSize(size: number): void { - if (size > this.size()) throw new RangeError('OUT_OF_BOUNDS'); - } - - public u8(): number { - this.assertSize(1); - const chunk = this.chunks[0]!; - let x = this.x; - const octet = chunk[x++]; - if (x === chunk.length) { - this.chunks.shift(); - this.chunkSize -= chunk.length; - x = 0; - } - this.x = x; - return octet; - } - - public u32(): number { - const octet0 = this.u8(); - const octet1 = this.u8(); - const octet2 = this.u8(); - const octet3 = this.u8(); - return (octet0 * 0x1000000 + (octet1 << 16) + (octet2 << 8)) | octet3; - } - - public copy(size: number, dst: Uint8Array, pos: number): void { - if (!size) return; - this.assertSize(size); - const chunk0 = this.chunks[0]!; - const size0 = Math.min(chunk0.length - this.x, size); - dst.set(chunk0.subarray(this.x, this.x + size0), pos); - size -= size0; - if (size <= 0) { - this.skipUnsafe(size0); - return; - } - let chunkIndex = 1; - while (size > 0) { - const chunk1 = this.chunks[chunkIndex]!; - const size1 = Math.min(chunk1.length, size); - dst.set(chunk1.subarray(0, size1), pos + size0); - size -= size1; - chunkIndex++; - } - this.skipUnsafe(size); - } - - public copyXor( - size: number, - dst: Uint8Array, - pos: number, - mask: [number, number, number, number], - maskIndex: number, - ): void { - if (!size) return; - this.assertSize(size); - const chunk0 = this.chunks[0]!; - let x = this.x; - const size0 = Math.min(chunk0.length - x, size); - const end = x + size0; - for (; x < end; ) dst[pos++] = chunk0[x++] ^ mask[maskIndex++ % 4]; - size -= size0; - if (size <= 0) { - this.skipUnsafe(size0); - return; - } - let chunkIndex = 1; - while (size > 0) { - const chunk1 = this.chunks[chunkIndex++]!; - const size1 = Math.min(chunk1.length, size); - for (let x = 0; x < size1; ) dst[pos++] = chunk1[x++] ^ mask[maskIndex++ % 4]; - size -= size1; - } - this.skipUnsafe(size); - } - - public buf(size: number): Uint8Array { - this.assertSize(size); - const buf = new Uint8Array(size); - this.copy(size, buf, 0); - return buf; - } - - public bufXor(size: number, mask: [number, number, number, number], maskIndex: number): Uint8Array { - this.assertSize(size); - const buf = new Uint8Array(size); - this.copyXor(size, buf, 0, mask, maskIndex); - return buf; - } - - public skipUnsafe(n: number): void { - if (!n) return; - const chunk = this.chunks[0]!; - const chunkLength = chunk.length; - const remaining = chunkLength - this.x; - if (remaining > n) { - this.x = this.x + n; - return; - } - this.x = 0; - this.chunks.shift(); - this.chunkSize -= chunkLength; - n -= remaining; - this.skipUnsafe(n); - } - - public skip(n: number): void { - this.assertSize(n); - this.skipUnsafe(n); - } - - public peak(): number { - this.assertSize(1); - return this.chunks[0]![this.x]; - } - - public utf8(length: number, mask: [number, number, number, number], maskIndex: number): string { - this.assertSize(length); - let i = 0; - const points: number[] = []; - while (i < length) { - let code = this.u8() ^ mask[maskIndex++ % 4]; - i++; - if ((code & 0x80) !== 0) { - const octet2 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f; - i++; - if ((code & 0xe0) === 0xc0) { - code = ((code & 0x1f) << 6) | octet2; - } else { - const octet3 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f; - i++; - if ((code & 0xf0) === 0xe0) { - code = ((code & 0x1f) << 12) | (octet2 << 6) | octet3; - } else { - if ((code & 0xf8) === 0xf0) { - const octet4 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f; - i++; - let unit = ((code & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800; - code = 0xdc00 | (unit & 0x3ff); - points.push(unit0); - } else { - code = unit; - } - } - } - } - } - points.push(code); - } - return fromCharCode.apply(String, points); - } -} diff --git a/src/util/buffers/StreamingReader.ts b/src/util/buffers/StreamingReader.ts deleted file mode 100644 index 1695b73711..0000000000 --- a/src/util/buffers/StreamingReader.ts +++ /dev/null @@ -1,179 +0,0 @@ -import {Writer} from './Writer'; -import {decodeUtf8} from './utf8/decodeUtf8'; -import type {IReader, IReaderResettable} from './types'; - -export class StreamingReader implements IReader, IReaderResettable { - protected readonly writer: Writer; - - /** - * Offset from the start of the buffer (x0 in Writer). - */ - protected dx = 0; - - constructor(allocSize: number = 16 * 1024) { - this.writer = new Writer(allocSize); - } - - /** - * Returns the number of bytes remaining in the buffer. - */ - public size(): number { - return this.writer.x - this.x; - } - - /** - * Assert that there is enough data in the buffer to read `size` bytes. - * - * @param size Number of bytes to read. - */ - protected assertSize(size: number): void { - if (size > this.size()) throw new RangeError('OUT_OF_BOUNDS'); - } - - /** - * Add a chunk of data to be decoded. The chunk is copied into the - * internal buffer, so you can reuse the chunk after calling this method; or - * this chunk can be neutered by the caller. - * - * @param uint8 `Uint8Array` chunk of data to be decoded. - */ - public push(uint8: Uint8Array): void { - this.writer.buf(uint8, uint8.length); - } - - /** - * Mark the current position as consumed. This will free up memory - * for reuse. - */ - public consume(): void { - this.writer.x0 += this.dx; - this.dx = 0; - } - - // ------------------------------------------------------------------ IReader - - public get uint8(): Uint8Array { - return this.writer.uint8; - } - - public get view(): DataView { - return this.writer.view; - } - - public get x(): number { - return this.writer.x0 + this.dx; - } - - public set x(x: number) { - this.dx = x - this.writer.x0; - } - - public peak(): number { - this.assertSize(1); - return this.view.getUint8(this.x); - } - - public skip(length: number): void { - this.assertSize(length); - this.x += length; - } - - public buf(size: number): Uint8Array { - this.assertSize(size); - const end = this.x + size; - const bin = this.uint8.subarray(this.x, end); - this.x = end; - return bin; - } - - public u8(): number { - this.assertSize(1); - return this.view.getUint8(this.x++); - } - - public i8(): number { - this.assertSize(1); - return this.view.getInt8(this.x++); - } - - public u16(): number { - this.assertSize(2); - const num = this.view.getUint16(this.x); - this.x += 2; - return num; - } - - public i16(): number { - this.assertSize(2); - const num = this.view.getInt16(this.x); - this.x += 2; - return num; - } - - public u32(): number { - this.assertSize(4); - const num = this.view.getUint32(this.x); - this.x += 4; - return num; - } - - public i32(): number { - this.assertSize(4); - const num = this.view.getInt32(this.x); - this.x += 4; - return num; - } - - public u64(): bigint { - this.assertSize(8); - const num = this.view.getBigUint64(this.x); - this.x += 8; - return num; - } - - public i64(): bigint { - this.assertSize(8); - const num = this.view.getBigInt64(this.x); - this.x += 8; - return num; - } - - public f32(): number { - this.assertSize(4); - const pos = this.x; - this.x += 4; - return this.view.getFloat32(pos); - } - - public f64(): number { - this.assertSize(8); - const pos = this.x; - this.x += 8; - return this.view.getFloat64(pos); - } - - public utf8(size: number): string { - this.assertSize(size); - const start = this.x; - this.x += size; - return decodeUtf8(this.uint8, start, size); - } - - public ascii(length: number): string { - this.assertSize(length); - const uint8 = this.uint8; - let str = ''; - const end = this.x + length; - for (let i = this.x; i < end; i++) str += String.fromCharCode(uint8[i]); - this.x = end; - return str; - } - - // -------------------------------------------------------- IReaderResettable - - public reset(uint8: Uint8Array): void { - this.dx = 0; - this.writer.reset(); - this.push(uint8); - } -} diff --git a/src/util/buffers/Uint8ArrayCut.ts b/src/util/buffers/Uint8ArrayCut.ts deleted file mode 100644 index b57bfd6d00..0000000000 --- a/src/util/buffers/Uint8ArrayCut.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class Uint8ArrayCut { - constructor( - public readonly uint8: Uint8Array, - public readonly start: number, - public readonly size: number, - ) {} -} diff --git a/src/util/buffers/Writer.ts b/src/util/buffers/Writer.ts deleted file mode 100644 index 8b96de2361..0000000000 --- a/src/util/buffers/Writer.ts +++ /dev/null @@ -1,269 +0,0 @@ -import {Slice} from './Slice'; -import {IWriterGrowable, IWriter} from './types'; - -const EMPTY_UINT8 = new Uint8Array([]); -const EMPTY_VIEW = new DataView(EMPTY_UINT8.buffer); - -const hasBuffer = typeof Buffer === 'function'; -const utf8Write = hasBuffer - ? (Buffer.prototype.utf8Write as (this: Uint8Array, str: string, pos: number, maxLength: number) => number) - : null; -const from = hasBuffer ? Buffer.from : null; -const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null; - -/** - * Encoder class provides an efficient way to encode binary data. It grows the - * internal memory buffer automatically as more space is required. It is useful - * in cases when it is not known in advance the size of memory needed. - */ -export class Writer implements IWriter, IWriterGrowable { - /** @ignore */ - public uint8: Uint8Array; - /** @ignore */ - public view: DataView = EMPTY_VIEW; - /** @ignore */ - public x0: number = 0; - /** @ignore */ - public x: number = 0; - protected size: number; - - /** - * @param allocSize Number of bytes to allocate at a time when buffer ends. - */ - constructor(public allocSize: number = 64 * 1024) { - this.uint8 = new Uint8Array(allocSize); - this.size = allocSize; - this.view = new DataView(this.uint8.buffer); - } - - /** @ignore */ - protected grow(size: number) { - const x0 = this.x0; - const x = this.x; - const oldUint8 = this.uint8; - const newUint8 = new Uint8Array(size); - const view = new DataView(newUint8.buffer); - const activeSlice = oldUint8.subarray(x0, x); - newUint8.set(activeSlice, 0); - this.x = x - x0; - this.x0 = 0; - this.uint8 = newUint8; - this.size = size; - this.view = view; - } - - /** - * Make sure the internal buffer has enough space to write the specified number - * of bytes, otherwise resize the internal buffer to accommodate for more size. - * - * @param capacity Number of bytes. - */ - public ensureCapacity(capacity: number) { - const byteLength = this.size; - const remaining = byteLength - this.x; - if (remaining < capacity) { - const total = byteLength - this.x0; - const required = capacity - remaining; - const totalRequired = total + required; - this.grow(totalRequired <= this.allocSize ? this.allocSize : totalRequired * 2); - } - } - - /** @todo Consider renaming to "skip"? */ - public move(capacity: number) { - this.ensureCapacity(capacity); - this.x += capacity; - } - - public reset() { - this.x0 = this.x; - } - - /** - * Allocates a new {@link ArrayBuffer}, useful when the underlying - * {@link ArrayBuffer} cannot be shared between threads. - * - * @param size Size of memory to allocate. - */ - public newBuffer(size: number) { - const uint8 = (this.uint8 = new Uint8Array(size)); - this.size = size; - this.view = new DataView(uint8.buffer); - this.x = this.x0 = 0; - } - - /** - * @returns Encoded memory buffer contents. - */ - public flush(): Uint8Array { - const result = this.uint8.subarray(this.x0, this.x); - this.x0 = this.x; - return result; - } - - public flushSlice(): Slice { - const slice = new Slice(this.uint8, this.view, this.x0, this.x); - this.x0 = this.x; - return slice; - } - - public u8(char: number) { - this.ensureCapacity(1); - this.uint8[this.x++] = char; - } - - public u16(word: number) { - this.ensureCapacity(2); - this.view.setUint16(this.x, word); - this.x += 2; - } - - public u32(dword: number) { - this.ensureCapacity(4); - this.view.setUint32(this.x, dword); - this.x += 4; - } - - public i32(dword: number) { - this.ensureCapacity(4); - this.view.setInt32(this.x, dword); - this.x += 4; - } - - public u64(qword: number | bigint) { - this.ensureCapacity(8); - this.view.setBigUint64(this.x, BigInt(qword)); - this.x += 8; - } - - public f64(float: number) { - this.ensureCapacity(8); - this.view.setFloat64(this.x, float); - this.x += 8; - } - - public u8u16(u8: number, u16: number) { - this.ensureCapacity(3); - let x = this.x; - this.uint8[x++] = u8; - this.uint8[x++] = u16 >>> 8; - this.uint8[x++] = u16 & 0xff; - this.x = x; - } - - public u8u32(u8: number, u32: number) { - this.ensureCapacity(5); - let x = this.x; - this.uint8[x++] = u8; - this.view.setUint32(x, u32); - this.x = x + 4; - } - - public u8u64(u8: number, u64: number | bigint) { - this.ensureCapacity(9); - let x = this.x; - this.uint8[x++] = u8; - this.view.setBigUint64(x, BigInt(u64)); - this.x = x + 8; - } - - public u8f32(u8: number, f32: number) { - this.ensureCapacity(5); - let x = this.x; - this.uint8[x++] = u8; - this.view.setFloat32(x, f32); - this.x = x + 4; - } - - public u8f64(u8: number, f64: number) { - this.ensureCapacity(9); - let x = this.x; - this.uint8[x++] = u8; - this.view.setFloat64(x, f64); - this.x = x + 8; - } - - public buf(buf: Uint8Array, length: number): void { - this.ensureCapacity(length); - const x = this.x; - this.uint8.set(buf, x); - this.x = x + length; - } - - /** - * Encodes string as UTF-8. You need to call .ensureCapacity(str.length * 4) - * before calling - * - * @param str String to encode as UTF-8. - * @returns The number of bytes written - */ - public utf8(str: string): number { - const maxLength = str.length * 4; - if (maxLength < 168) return this.utf8Native(str); - if (utf8Write) { - const writeLength = utf8Write.call(this.uint8, str, this.x, maxLength); - this.x += writeLength; - return writeLength; - } else if (from) { - const uint8 = this.uint8; - const offset = uint8.byteOffset + this.x; - const buf = from(uint8.buffer).subarray(offset, offset + maxLength); - const writeLength = buf.write(str, 0, maxLength, 'utf8'); - this.x += writeLength; - return writeLength; - } else if (maxLength > 1024 && textEncoder) { - const writeLength = textEncoder!.encodeInto(str, this.uint8.subarray(this.x, this.x + maxLength)).written!; - this.x += writeLength; - return writeLength; - } - return this.utf8Native(str); - } - - public utf8Native(str: string): number { - const length = str.length; - const uint8 = this.uint8; - let offset = this.x; - let pos = 0; - while (pos < length) { - let value = str.charCodeAt(pos++); - if ((value & 0xffffff80) === 0) { - uint8[offset++] = value; - continue; - } else if ((value & 0xfffff800) === 0) { - uint8[offset++] = ((value >> 6) & 0x1f) | 0xc0; - } else { - if (value >= 0xd800 && value <= 0xdbff) { - if (pos < length) { - const extra = str.charCodeAt(pos); - if ((extra & 0xfc00) === 0xdc00) { - pos++; - value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; - } - } - } - if ((value & 0xffff0000) === 0) { - uint8[offset++] = ((value >> 12) & 0x0f) | 0xe0; - uint8[offset++] = ((value >> 6) & 0x3f) | 0x80; - } else { - uint8[offset++] = ((value >> 18) & 0x07) | 0xf0; - uint8[offset++] = ((value >> 12) & 0x3f) | 0x80; - uint8[offset++] = ((value >> 6) & 0x3f) | 0x80; - } - } - uint8[offset++] = (value & 0x3f) | 0x80; - } - const writeLength = offset - this.x; - this.x = offset; - return writeLength; - } - - public ascii(str: string): void { - const length = str.length; - this.ensureCapacity(length); - const uint8 = this.uint8; - let x = this.x; - let pos = 0; - while (pos < length) uint8[x++] = str.charCodeAt(pos++); - this.x = x; - } -} diff --git a/src/util/buffers/__bench__/bench.decodeUtf8.ts b/src/util/buffers/__bench__/bench.decodeUtf8.ts deleted file mode 100644 index 0baee0ff6d..0000000000 --- a/src/util/buffers/__bench__/bench.decodeUtf8.ts +++ /dev/null @@ -1,108 +0,0 @@ -// yarn build && npx ts-node src/util/buffers/__bench__/bench.decodeUtf8.ts - -import {runBenchmark} from '../../../__bench__/runBenchmark'; - -const prepare = (str: string) => { - const buf = Buffer.from(str); - const arr = new Uint8Array(buf.length); - for (let i = 0; i < buf.length; i++) arr[i] = buf[i]; - return arr; -}; - -const runner = (v: number, name: string) => ({ - name: `${name} (v${v})`, - setup: () => { - const decode = require('../../../../lib/util/buffers/utf8/decodeUtf8/v' + v).default; - return (data: any) => decode(data, 0, data.length); - }, -}); - -const benchmark = { - name: 'decodeUtf8', - warmup: 1000, - payloads: [ - // { - // name: (buf) => `Single character, ${buf.length} bytes`, - // data: prepare('a'), - // test: () => 'a', - // }, - // { - // name: (buf) => `"Hello", ${buf.length} bytes`, - // data: prepare('Hello'), - // test: () => 'Hello', - // }, - // { - // name: (buf) => `Short text with emoji, ${buf.length} bytes`, - // data: prepare('Hi, Mike 👋!'), - // test: () => 'Hi, Mike 👋!', - // }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('a'.repeat(2)), - test: () => 'a'.repeat(2), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('a'.repeat(4)), - test: () => 'a'.repeat(4), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('a'.repeat(8)), - test: () => 'a'.repeat(8), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(3)), - test: () => 'abcd'.repeat(3), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(4)), - test: () => 'abcd'.repeat(4), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(8)), - test: () => 'abcd'.repeat(8), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(16)), - test: () => 'abcd'.repeat(16), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(32)), - test: () => 'abcd'.repeat(32), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(64)), - test: () => 'abcd'.repeat(64), - }, - { - name: (buf: any) => `Repeating characters, ${buf.length} bytes`, - data: prepare('abcd'.repeat(128)), - test: () => 'abcd'.repeat(128), - }, - ], - runners: [ - // runner(1, 'JS with buffering in array'), - // runner(2, 'Buffer.prototype.utf8Slice'), - // runner(3, 'Buffer.from(arr).slice'), - // runner(4, 'Buffer.from(arr).subarray'), - // runner(5, 'JS with string concatenation'), - // runner(6, 'TextDecoder'), - // runner(7, 'JS with buffering in array, no flushing'), - // runner(8, 'JS with buffering in array, small buffer'), - // runner(9, 'JS with buffering in array, variable reuse'), - // runner(10, 'JS with string concatenation, variable reuse'), - runner(19, 'json-pack-napi'), - runner(11, 'utf8Slice'), - // runner(12, 'from(arr).subarray'), - // runner(13, 'composition'), - ], -}; - -runBenchmark(benchmark); diff --git a/src/util/buffers/__tests__/StreamingReader.spec.ts b/src/util/buffers/__tests__/StreamingReader.spec.ts deleted file mode 100644 index 420dbfa311..0000000000 --- a/src/util/buffers/__tests__/StreamingReader.spec.ts +++ /dev/null @@ -1,57 +0,0 @@ -import {StreamingReader} from '../StreamingReader'; - -test('can push and read', () => { - const reader = new StreamingReader(4); - reader.push(new Uint8Array([1, 2, 3])); - expect(reader.u8()).toBe(1); - reader.push(new Uint8Array([4, 5, 6])); - expect(reader.u8()).toBe(2); - expect(reader.u8()).toBe(3); - expect(reader.u8()).toBe(4); - expect(reader.u8()).toBe(5); - expect(reader.u8()).toBe(6); -}); - -test('throws RangeError when reading out of bounds', () => { - const reader = new StreamingReader(2); - reader.push(new Uint8Array([1, 2, 3])); - reader.u16(); - reader.u8(); - expect(() => reader.u8()).toThrow(RangeError); -}); - -test('throws RangeError when reading out of bounds - 2', () => { - const reader = new StreamingReader(); - reader.push(new Uint8Array([1, 2, 3])); - reader.u16(); - expect(() => reader.u16()).toThrow(RangeError); -}); - -test('throws RangeError when reading out of bounds - 3', () => { - const reader = new StreamingReader(4); - reader.push(new Uint8Array([1, 2, 3])); - reader.u16(); - reader.push(new Uint8Array([4, 5])); - expect(() => reader.u32()).toThrow(RangeError); -}); - -test('size shrinks as data is read', () => { - const reader = new StreamingReader(4); - expect(reader.size()).toBe(0); - reader.push(new Uint8Array([1, 2, 3])); - expect(reader.size()).toBe(3); - expect(reader.u8()).toBe(1); - expect(reader.size()).toBe(2); - reader.push(new Uint8Array([4, 5, 6])); - expect(reader.size()).toBe(5); - expect(reader.u8()).toBe(2); - expect(reader.size()).toBe(4); - expect(reader.u8()).toBe(3); - expect(reader.size()).toBe(3); - expect(reader.u8()).toBe(4); - expect(reader.size()).toBe(2); - expect(reader.u8()).toBe(5); - expect(reader.size()).toBe(1); - expect(reader.u8()).toBe(6); - expect(reader.size()).toBe(0); -}); diff --git a/src/util/buffers/__tests__/isFloat32.spec.ts b/src/util/buffers/__tests__/isFloat32.spec.ts deleted file mode 100644 index 34a21049f3..0000000000 --- a/src/util/buffers/__tests__/isFloat32.spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {isFloat32} from '../isFloat32'; - -test('returns true for a float32', () => { - expect(isFloat32(1.5)).toBe(true); -}); - -test('returns true for a float64', () => { - expect(isFloat32(1.1)).toBe(false); -}); diff --git a/src/util/buffers/b.ts b/src/util/buffers/b.ts deleted file mode 100644 index 003f912314..0000000000 --- a/src/util/buffers/b.ts +++ /dev/null @@ -1 +0,0 @@ -export const b = (...args: number[]) => new Uint8Array(args); diff --git a/src/util/buffers/bufferToUint8Array.ts b/src/util/buffers/bufferToUint8Array.ts deleted file mode 100644 index 63598b6434..0000000000 --- a/src/util/buffers/bufferToUint8Array.ts +++ /dev/null @@ -1 +0,0 @@ -export const bufferToUint8Array = (buf: Buffer): Uint8Array => new Uint8Array(buf.buffer, buf.byteOffset, buf.length); diff --git a/src/util/buffers/cmpUint8Array.ts b/src/util/buffers/cmpUint8Array.ts deleted file mode 100644 index 694c0275e9..0000000000 --- a/src/util/buffers/cmpUint8Array.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const cmpUint8Array = (a: Uint8Array, b: Uint8Array): boolean => { - const length = a.length; - if (length !== b.length) return false; - for (let i = 0; i < length; i++) if (a[i] !== b[i]) return false; - return true; -}; diff --git a/src/util/buffers/cmpUint8Array2.ts b/src/util/buffers/cmpUint8Array2.ts deleted file mode 100644 index 344ec1e6f2..0000000000 --- a/src/util/buffers/cmpUint8Array2.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Compares two `Uint8Arrays` byte-by-byte. Returns a negative number if `a` is - * less than `b`, a positive number if `a` is greater than `b`, or 0 if `a` is - * equal to `b`. - * - * @returns A negative number if a is less than b, a positive number if a is - * greater than b, or 0 if a is equal to b. - */ -export const cmpUint8Array2 = (a: Uint8Array, b: Uint8Array): number => { - const len1 = a.length; - const len2 = b.length; - const len = Math.min(len1, len2); - for (let i = 0; i < len; i++) { - const diffChar = a[i] - b[i]; - if (diffChar !== 0) return diffChar; - } - return len1 - len2; -}; diff --git a/src/util/buffers/cmpUint8Array3.ts b/src/util/buffers/cmpUint8Array3.ts deleted file mode 100644 index 950c358f7e..0000000000 --- a/src/util/buffers/cmpUint8Array3.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Compares two `Uint8Arrays`, first by length, then by each byte. Returns a - * negative number if `a` is less than `b`, a positive number if `a` is greater - * than `b`, or 0 if `a` is equal to `b`. - * - * @returns A negative number if a is less than b, a positive number if a is - * greater than b, or 0 if a is equal to b. - */ -export const cmpUint8Array3 = (a: Uint8Array, b: Uint8Array): number => { - const len1 = a.length; - const len2 = b.length; - const diff = len1 - len2; - if (diff !== 0) return diff; - for (let i = 0; i < len1; i++) { - const diff = a[i] - b[i]; - if (diff !== 0) return diff; - } - return 0; -}; diff --git a/src/util/buffers/concat.ts b/src/util/buffers/concat.ts deleted file mode 100644 index 205bad1d4b..0000000000 --- a/src/util/buffers/concat.ts +++ /dev/null @@ -1,31 +0,0 @@ -export const concat = (a: Uint8Array, b: Uint8Array): Uint8Array => { - const res = new Uint8Array(a.length + b.length); - res.set(a); - res.set(b, a.length); - return res; -}; - -export const concatList = (list: Uint8Array[]): Uint8Array => { - const length = list.length; - let size = 0, - offset = 0; - for (let i = 0; i < length; i++) size += list[i].length; - const res = new Uint8Array(size); - for (let i = 0; i < length; i++) { - const item = list[i]; - res.set(item, offset); - offset += item.length; - } - return res; -}; - -export const listToUint8 = (list: Uint8Array[]): Uint8Array => { - switch (list.length) { - case 0: - return new Uint8Array(0); - case 1: - return list[0]; - default: - return concatList(list); - } -}; diff --git a/src/util/buffers/copy.ts b/src/util/buffers/copy.ts deleted file mode 100644 index d779133967..0000000000 --- a/src/util/buffers/copy.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const copy = (arr: T): T => { - const dupe = new Uint8Array(arr.length) as T; - dupe.set(arr); - return dupe; -}; diff --git a/src/util/buffers/f16.ts b/src/util/buffers/f16.ts deleted file mode 100644 index 51a4150413..0000000000 --- a/src/util/buffers/f16.ts +++ /dev/null @@ -1,16 +0,0 @@ -const pow = Math.pow; - -export const decodeF16 = (binary: number): number => { - const exponent = (binary & 0x7c00) >> 10; - const fraction = binary & 0x03ff; - return ( - (binary >> 15 ? -1 : 1) * - (exponent - ? exponent === 0x1f - ? fraction - ? NaN - : Infinity - : pow(2, exponent - 15) * (1 + fraction / 0x400) - : 6.103515625e-5 * (fraction / 0x400)) - ); -}; diff --git a/src/util/buffers/index.ts b/src/util/buffers/index.ts index fcb073fefc..7d1d7e6433 100644 --- a/src/util/buffers/index.ts +++ b/src/util/buffers/index.ts @@ -1 +1 @@ -export * from './types'; +export * from '@jsonjoy.com/json-pack/lib/util/buffers'; diff --git a/src/util/buffers/isArrayBuffer.ts b/src/util/buffers/isArrayBuffer.ts deleted file mode 100644 index 998e906535..0000000000 --- a/src/util/buffers/isArrayBuffer.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isArrayBuffer = (value: unknown): value is ArrayBuffer => { - return value instanceof ArrayBuffer || toString.call(value) === '[object ArrayBuffer]'; -}; diff --git a/src/util/buffers/isFloat32.ts b/src/util/buffers/isFloat32.ts deleted file mode 100644 index 26e382346d..0000000000 --- a/src/util/buffers/isFloat32.ts +++ /dev/null @@ -1,6 +0,0 @@ -const view = new DataView(new ArrayBuffer(4)); - -export const isFloat32 = (n: number): boolean => { - view.setFloat32(0, n); - return n === view.getFloat32(0); -}; diff --git a/src/util/buffers/isUint8Array.ts b/src/util/buffers/isUint8Array.ts deleted file mode 100644 index b86a8b0659..0000000000 --- a/src/util/buffers/isUint8Array.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const isUint8Array = - typeof Buffer === 'function' - ? (x: unknown): x is Uint8Array => x instanceof Uint8Array || Buffer.isBuffer(x) - : (x: unknown): x is Uint8Array => x instanceof Uint8Array; diff --git a/src/util/buffers/printOctets.ts b/src/util/buffers/printOctets.ts deleted file mode 100644 index 9e5c01fd3e..0000000000 --- a/src/util/buffers/printOctets.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const printOctets = (octets: Uint8Array, max: number = 16): string => { - let str = ''; - if (!octets.length) return str; - if (octets[0] < 16) str += '0'; - str += octets[0].toString(16); - for (let i = 1; i < octets.length && i < max; i++) { - const n = octets[i]; - str += ' '; - if (n < 16) str += '0'; - str += n.toString(16); - } - if (octets.length > max) str += `… (${octets.length - max} more)`; - return str; -}; diff --git a/src/util/buffers/strings.ts b/src/util/buffers/strings.ts deleted file mode 100644 index f4ac5b7378..0000000000 --- a/src/util/buffers/strings.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {bufferToUint8Array} from './bufferToUint8Array'; - -export const ascii = (txt: TemplateStringsArray | string | [string]): Uint8Array => { - if (typeof txt === 'string') return ascii([txt]); - [txt] = txt; - const len = txt.length; - const res = new Uint8Array(len); - for (let i = 0; i < len; i++) res[i] = txt.charCodeAt(i); - return res; -}; - -export const utf8 = (txt: TemplateStringsArray | [string] | string): Uint8Array => { - if (typeof txt === 'string') return utf8([txt]); - [txt] = txt; - return bufferToUint8Array(Buffer.from(txt, 'utf8')); -}; diff --git a/src/util/buffers/toBuf.ts b/src/util/buffers/toBuf.ts deleted file mode 100644 index 576f8a517f..0000000000 --- a/src/util/buffers/toBuf.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {encode} from './utf8/encode'; - -export const toBuf = (str: string): Uint8Array => { - const maxLength = str.length * 4; - const arr = new Uint8Array(maxLength); - const strBufferLength = encode(arr, str, 0, maxLength); - return arr.slice(0, strBufferLength); -}; diff --git a/src/util/buffers/toDataUri.ts b/src/util/buffers/toDataUri.ts deleted file mode 100644 index b5f26dab12..0000000000 --- a/src/util/buffers/toDataUri.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {toBase64} from '../base64'; - -export const toDataUri = (buf: Uint8Array, params?: Record): string => { - let uri = 'data:application/octet-stream;base64'; - for (const key in params) uri += `;${key}=${params[key]}`; - return uri + ',' + toBase64(buf); -}; diff --git a/src/util/buffers/toUint8Array.ts b/src/util/buffers/toUint8Array.ts deleted file mode 100644 index 8e2c916816..0000000000 --- a/src/util/buffers/toUint8Array.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const toUint8Array = (data: unknown): Uint8Array => { - if (data instanceof Uint8Array) return data; - if (data instanceof ArrayBuffer) return new Uint8Array(data); - if (Array.isArray(data)) return new Uint8Array(data); - if (typeof Buffer === 'function') { - if (Buffer.isBuffer(data)) return data; - return Buffer.from(data as any); - } - throw new Error('UINT8ARRAY_INCOMPATIBLE'); -}; diff --git a/src/util/buffers/types.ts b/src/util/buffers/types.ts deleted file mode 100644 index ae29727a81..0000000000 --- a/src/util/buffers/types.ts +++ /dev/null @@ -1,126 +0,0 @@ -import type {Slice} from './Slice'; - -export interface IWriter { - /** - * Uint8Array view of the current memory buffer. - */ - uint8: Uint8Array; - - /** - * DataView view of the current memory buffer. - */ - view: DataView; - - /** - * Position where last flush happened. - */ - x0: number; - - /** - * Current position in the internal buffer. - */ - x: number; - - u8(char: number): void; - u16(word: number): void; - u32(dword: number): void; - i32(dword: number): void; - u64(qword: number | bigint): void; - u8u16(u8: number, u16: number): void; - u8u32(u8: number, u32: number): void; - u8u64(u8: number, u64: number | bigint): void; - u8f32(u8: number, f64: number): void; - u8f64(u8: number, f64: number): void; - f64(dword: number): void; - - /** - * Write contents of a buffer. - * - * @param buf Buffer to copy from. - * @param length Number of octets to copy. - */ - buf(buf: Uint8Array, length: number): void; - - /** - * Write string as UTF-8. You need to call .ensureCapacity(str.length * 4) - * before calling - * - * @param str JavaScript string to encode as UTF-8 byte sequence. - */ - utf8(str: string): number; - - ascii(str: string): void; -} - -export interface IWriterGrowable { - /** @deprecated */ - reset(): void; - - /** - * Calling this method might reset the internal buffer. So, your references - * (such as `x`, `uint8`, `view`) to the internal buffer might become invalid. - * - * @param capacity How many octets to ensure are available after `x`. - */ - ensureCapacity(capacity: number): void; - move(length: number): void; - flush(): Uint8Array; - flushSlice(): Slice; - newBuffer(size: number): void; -} - -export interface IReaderBase { - /** Get current byte value without advancing the cursor. */ - peak(): number; - - /** Advance the cursor given number of octets. */ - skip(length: number): void; - - /** - * Create a new Uint8Array view of provided length starting at - * the current cursor position. - */ - buf(size: number): Uint8Array; - - u8(): number; - i8(): number; - u16(): number; - i16(): number; - u32(): number; - u64(): bigint; - i64(): bigint; - i32(): number; - f32(): number; - f64(): number; - - /** - * Decode a UTF-8 string. - * - * @param size Length of the string. - */ - utf8(size: number): string; - - ascii(length: number): string; -} - -export interface IReader extends IReaderBase { - /** - * Uint8Array view of the current memory buffer. - */ - uint8: Uint8Array; - - /** - * DataView view of the current memory buffer. - */ - view: DataView; - - /** - * Cursor in the current memory buffer. - */ - x: number; -} - -export interface IReaderResettable { - /** Set a new underlying buffer and reset cursor position to 0. */ - reset(uint8: Uint8Array): void; -} diff --git a/src/util/buffers/utf8/CachedUtf8Decoder.ts b/src/util/buffers/utf8/CachedUtf8Decoder.ts deleted file mode 100644 index 01dd36f9b7..0000000000 --- a/src/util/buffers/utf8/CachedUtf8Decoder.ts +++ /dev/null @@ -1,54 +0,0 @@ -import decodeUtf8 from './decodeUtf8/v10'; -import {randomU32} from 'hyperdyperid/lib/randomU32'; - -class CacheItem { - constructor( - public readonly bytes: Uint8Array, - public readonly value: string, - ) {} -} - -const enum CONST { - MAX_CACHED_STR_LEN = 31, - MAX_RECORDS_PER_SIZE = 16, -} - -export class CachedUtf8Decoder { - private readonly caches: CacheItem[][]; - - constructor() { - this.caches = []; - for (let i = 0; i < CONST.MAX_CACHED_STR_LEN; i++) this.caches.push([]); - } - - private get(bytes: Uint8Array, offset: number, size: number): string | null { - const records = this.caches[size - 1]!; - const len = records.length; - FIND_CHUNK: for (let i = 0; i < len; i++) { - const record = records[i]; - const recordBytes = record.bytes; - for (let j = 0; j < size; j++) if (recordBytes[j] !== bytes[offset + j]) continue FIND_CHUNK; - return record.value; - } - return null; - } - - private store(bytes: Uint8Array, value: string): void { - const records = this.caches[bytes.length - 1]!; - const record = new CacheItem(bytes, value); - const length = records.length; - if (length >= CONST.MAX_RECORDS_PER_SIZE) records[randomU32(0, CONST.MAX_RECORDS_PER_SIZE - 1)] = record; - else records.push(record); - } - - public decode(bytes: Uint8Array, offset: number, size: number): string { - if (!size) return ''; - const cachedValue = this.get(bytes, offset, size); - if (cachedValue !== null) return cachedValue; - const value = decodeUtf8(bytes, offset, size); - // Ensure to copy a slice of bytes because the byte may be NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer. - const copy = Uint8Array.prototype.slice.call(bytes, offset, offset + size); - this.store(copy, value); - return value; - } -} diff --git a/src/util/buffers/utf8/__tests__/encode.spec.ts b/src/util/buffers/utf8/__tests__/encode.spec.ts deleted file mode 100644 index 5aeea13300..0000000000 --- a/src/util/buffers/utf8/__tests__/encode.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {RandomJson} from '../../../../json-random'; -import {encodeUtf8Write, encodeFrom, encodeNative, encodeTe, encode, EncodeString} from '../encode'; - -describe('can encode JavaScript string as UTF-8 string', () => { - const runEncodingTest = (name: string, encode: EncodeString) => { - test(name, () => { - const arr = new Uint8Array(50); - for (let i = 0; i < 1000; i++) { - const str = RandomJson.genString(10); - const len = encode(arr, str, str.length, str.length * 4); - const slice = arr.subarray(10, 10 + len); - const decoded = Buffer.from(slice).toString(); - expect(decoded).toBe(str); - } - }); - }; - - runEncodingTest('encodeUtf8Write', encodeUtf8Write); - runEncodingTest('encodeFrom', encodeFrom); - runEncodingTest('encodeNative', encodeNative); - runEncodingTest('encodeTe', encodeTe); - runEncodingTest('encode', encode); -}); diff --git a/src/util/buffers/utf8/__tests__/isUtf8.spec.ts b/src/util/buffers/utf8/__tests__/isUtf8.spec.ts deleted file mode 100644 index 6ea5aea23e..0000000000 --- a/src/util/buffers/utf8/__tests__/isUtf8.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {isUtf8} from '../isUtf8'; - -describe('returns true for valid UTF8', () => { - const strings = [ - '', - 'hello', - 'hello world', - 'emoji: 🤔', - 'russian: Привет', - 'chinese: 你好', - 'japanese: こんにちは', - 'korean: 안녕하세요', - 'arabic: مرحبا', - 'hebrew: שלום', - 'greek: γεια σας', - 'bulgarian: Здравейте', - 'hindi: नमस्ते', - 'thai: สวัสดี', - 'special chars: !@#$%^&*()_+{}|:"<>?`-=[]\\;\',./', - ]; - for (const str of strings) { - test(str, () => { - const buf = Buffer.from(str); - expect(isUtf8(buf, 0, buf.length)).toBe(true); - }); - } -}); - -describe('returns false for non-UTF8 sequences', () => { - const strings: [name: string, Uint8Array][] = [ - ['two octets', Buffer.from([0xc3, 0x28])], - ['three octets', Buffer.from([0xe2, 0x82, 0x28])], - ['four octets', Buffer.from([0xf0, 0x90, 0x82, 0x28])], - ['five octets', Buffer.from([0xf8, 0x88, 0x82, 0x82, 0x28])], - ['six octets', Buffer.from([0xfc, 0x84, 0x82, 0x82, 0x82, 0x28])], - ]; - for (const [name, str] of strings) { - test(name, () => { - expect(isUtf8(str, 0, str.length)).toBe(false); - }); - } -}); - -describe('returns true for valid non-UTF8 sequences in the middle of buffer', () => { - const strings: [name: string, str: Uint8Array, from: number, length: number][] = [ - ['mid char valid', Buffer.from([0xc3, 0x28, 64, 0xc3, 0x28]), 2, 1], - ]; - for (const [name, str, from, length] of strings) { - test(name, () => { - expect(isUtf8(str, from, length)).toBe(true); - expect(isUtf8(str, 0, from + length)).toBe(false); - }); - } -}); diff --git a/src/util/buffers/utf8/decodeAscii.ts b/src/util/buffers/utf8/decodeAscii.ts deleted file mode 100644 index cb84c50de8..0000000000 --- a/src/util/buffers/utf8/decodeAscii.ts +++ /dev/null @@ -1,167 +0,0 @@ -const fromCharCode = String.fromCharCode; - -/** This code was borrowed form cbor-x under the MIT license. */ - -// MIT License - -// Copyright (c) 2020 Kris Zyp - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -export const decodeAscii = (src: Uint8Array, position: number, length: number): string | undefined => { - const bytes = []; - for (let i = 0; i < length; i++) { - const byte = src[position++]; - if (byte & 0x80) return; - bytes.push(byte); - } - return fromCharCode.apply(String, bytes); -}; - -export const decodeAsciiMax15 = (src: Uint8Array, position: number, length: number): string | undefined => { - if (length < 4) { - if (length < 2) { - if (length === 0) return ''; - else { - const a = src[position++]; - if ((a & 0x80) > 1) { - position -= 1; - return; - } - return fromCharCode(a); - } - } else { - const a = src[position++]; - const b = src[position++]; - if ((a & 0x80) > 0 || (b & 0x80) > 0) { - position -= 2; - return; - } - if (length < 3) return fromCharCode(a, b); - const c = src[position++]; - if ((c & 0x80) > 0) { - position -= 3; - return; - } - return fromCharCode(a, b, c); - } - } else { - const a = src[position++]; - const b = src[position++]; - const c = src[position++]; - const d = src[position++]; - if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) { - position -= 4; - return; - } - if (length < 6) { - if (length === 4) return fromCharCode(a, b, c, d); - else { - const e = src[position++]; - if ((e & 0x80) > 0) { - position -= 5; - return; - } - return fromCharCode(a, b, c, d, e); - } - } else if (length < 8) { - const e = src[position++]; - const f = src[position++]; - if ((e & 0x80) > 0 || (f & 0x80) > 0) { - position -= 6; - return; - } - if (length < 7) return fromCharCode(a, b, c, d, e, f); - const g = src[position++]; - if ((g & 0x80) > 0) { - position -= 7; - return; - } - return fromCharCode(a, b, c, d, e, f, g); - } else { - const e = src[position++]; - const f = src[position++]; - const g = src[position++]; - const h = src[position++]; - if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) { - position -= 8; - return; - } - if (length < 10) { - if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h); - else { - const i = src[position++]; - if ((i & 0x80) > 0) { - position -= 9; - return; - } - return fromCharCode(a, b, c, d, e, f, g, h, i); - } - } else if (length < 12) { - const i = src[position++]; - const j = src[position++]; - if ((i & 0x80) > 0 || (j & 0x80) > 0) { - position -= 10; - return; - } - if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j); - const k = src[position++]; - if ((k & 0x80) > 0) { - position -= 11; - return; - } - return fromCharCode(a, b, c, d, e, f, g, h, i, j, k); - } else { - const i = src[position++]; - const j = src[position++]; - const k = src[position++]; - const l = src[position++]; - if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) { - position -= 12; - return; - } - if (length < 14) { - if (length === 12) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l); - else { - const m = src[position++]; - if ((m & 0x80) > 0) { - position -= 13; - return; - } - return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m); - } - } else { - const m = src[position++]; - const n = src[position++]; - if ((m & 0x80) > 0 || (n & 0x80) > 0) { - position -= 14; - return; - } - if (length < 15) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n); - const o = src[position++]; - if ((o & 0x80) > 0) { - position -= 15; - return; - } - return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); - } - } - } - } -}; diff --git a/src/util/buffers/utf8/decodeUtf8/README.md b/src/util/buffers/utf8/decodeUtf8/README.md deleted file mode 100644 index dbdea0c7be..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/README.md +++ /dev/null @@ -1,96 +0,0 @@ -# `decodeUtf8` - -Decodes UTF-8 text from `Uint8Array` buffer to JavaScript string (UTF-16). - -- `Buffer.from(arr).subarray` (v4) is always faster than `Buffer.from(arr).slice` (v3). -- `Buffer.prototype.utf8Slice` (v2) is always faster than `Buffer.from(arr).subarray` (v4). - - But `Buffer.prototype.utf8Slice` (v2) is Node's internal implementation detail, so we need - to be able to fall back to `Buffer.from(arr).subarray` (v4). -- "JS with string concatenation" (v5) is fastest for tiny strings. -- "JS with buffering in array" (v1) is fastest for medium sized strings. -- `TextDecoder` (v6) is slower than any `Buffer` methods. - - However, `Buffer` is not available on the browser (and possibly other environments). So, - for long strings would be beneficial to use `TextDecoder` (v6). -- (v10) seems to be faster than (v5). -- (v9) seems to be the fastest out of the buffering approaches. - - -Benchmarks: - -``` -node benchmarks/util/buffers/bench.decodeUtf8.js -============================================================================= Benchmark: decodeUtf8 -Warming up each runner 1000x -------------------------------------------------------------------------- Single character, 1 bytes -👍 JS with buffering in array (v1) x 45,587,314 ops/sec ±0.35% (91 runs sampled) -👍 Buffer.prototype.utf8Slice (v2) x 9,669,294 ops/sec ±0.08% (95 runs sampled) -👍 Buffer.from(arr).slice (v3) x 6,522,838 ops/sec ±0.18% (93 runs sampled) -👍 Buffer.from(arr).subarray (v4) x 7,004,453 ops/sec ±0.17% (99 runs sampled) -👍 JS with string concatenation (v5) x 157,127,790 ops/sec ±0.08% (98 runs sampled) -👍 TextDecoder (v6) x 1,405,754 ops/sec ±1.57% (84 runs sampled) -Fastest is 👍 JS with string concatenation (v5) ----------------------------------------------------------------------------------- "Hello", 5 bytes -👍 JS with buffering in array (v1) x 26,293,330 ops/sec ±0.17% (98 runs sampled) -👍 Buffer.prototype.utf8Slice (v2) x 9,595,299 ops/sec ±0.13% (97 runs sampled) -👍 Buffer.from(arr).slice (v3) x 6,597,346 ops/sec ±0.27% (90 runs sampled) -👍 Buffer.from(arr).subarray (v4) x 6,913,974 ops/sec ±0.17% (98 runs sampled) -👍 JS with string concatenation (v5) x 33,109,095 ops/sec ±0.17% (100 runs sampled) -👍 TextDecoder (v6) x 1,393,950 ops/sec ±1.31% (87 runs sampled) -Fastest is 👍 JS with string concatenation (v5) -------------------------------------------------------------------- Short text with emoji, 14 bytes -👍 JS with buffering in array (v1) x 13,746,402 ops/sec ±0.61% (94 runs sampled) -👍 Buffer.prototype.utf8Slice (v2) x 8,573,654 ops/sec ±0.13% (99 runs sampled) -👍 Buffer.from(arr).slice (v3) x 6,003,418 ops/sec ±0.42% (97 runs sampled) -👍 Buffer.from(arr).subarray (v4) x 6,163,374 ops/sec ±0.35% (99 runs sampled) -👍 JS with string concatenation (v5) x 7,468,848 ops/sec ±0.26% (99 runs sampled) -👍 TextDecoder (v6) x 1,358,357 ops/sec ±1.32% (72 runs sampled) -Fastest is 👍 JS with buffering in array (v1) ---------------------------------------------------------------------- Repeating characters, 8 bytes -👍 JS with buffering in array (v1) x 18,606,797 ops/sec ±0.37% (99 runs sampled) -👍 Buffer.prototype.utf8Slice (v2) x 9,210,861 ops/sec ±0.26% (99 runs sampled) -👍 Buffer.from(arr).slice (v3) x 6,398,227 ops/sec ±0.23% (96 runs sampled) -👍 Buffer.from(arr).subarray (v4) x 6,820,514 ops/sec ±0.22% (99 runs sampled) -👍 JS with string concatenation (v5) x 17,943,107 ops/sec ±0.35% (94 runs sampled) -👍 TextDecoder (v6) x 1,448,300 ops/sec ±1.36% (75 runs sampled) -Fastest is 👍 JS with buffering in array (v1) --------------------------------------------------------------------- Repeating characters, 16 bytes -🤞 JS with buffering in array (v1) x 12,181,356 ops/sec ±0.26% (100 runs sampled) -🤞 Buffer.prototype.utf8Slice (v2) x 9,254,890 ops/sec ±0.25% (97 runs sampled) -🤞 Buffer.from(arr).slice (v3) x 6,407,754 ops/sec ±0.20% (99 runs sampled) -🤞 Buffer.from(arr).subarray (v4) x 6,738,914 ops/sec ±0.25% (98 runs sampled) -🤞 JS with string concatenation (v5) x 9,530,473 ops/sec ±0.21% (101 runs sampled) -🤞 TextDecoder (v6) x 1,456,139 ops/sec ±1.28% (77 runs sampled) -Fastest is 🤞 JS with buffering in array (v1) --------------------------------------------------------------------- Repeating characters, 32 bytes -🤞 JS with buffering in array (v1) x 6,327,652 ops/sec ±0.24% (100 runs sampled) -🤞 Buffer.prototype.utf8Slice (v2) x 8,958,249 ops/sec ±0.22% (99 runs sampled) -🤞 Buffer.from(arr).slice (v3) x 6,217,455 ops/sec ±0.23% (98 runs sampled) -🤞 Buffer.from(arr).subarray (v4) x 6,500,127 ops/sec ±0.18% (101 runs sampled) -🤞 JS with string concatenation (v5) x 5,647,992 ops/sec ±0.14% (99 runs sampled) -🤞 TextDecoder (v6) x 1,452,152 ops/sec ±1.26% (79 runs sampled) -Fastest is 🤞 Buffer.prototype.utf8Slice (v2) --------------------------------------------------------------------- Repeating characters, 64 bytes -🤞 JS with buffering in array (v1) x 3,141,539 ops/sec ±0.23% (99 runs sampled) -🤞 Buffer.prototype.utf8Slice (v2) x 8,898,315 ops/sec ±0.21% (99 runs sampled) -🤞 Buffer.from(arr).slice (v3) x 5,947,900 ops/sec ±0.24% (99 runs sampled) -🤞 Buffer.from(arr).subarray (v4) x 6,380,096 ops/sec ±0.17% (102 runs sampled) -🤞 JS with string concatenation (v5) x 3,027,083 ops/sec ±0.15% (96 runs sampled) -🤞 TextDecoder (v6) x 1,387,153 ops/sec ±0.86% (85 runs sampled) -Fastest is 🤞 Buffer.prototype.utf8Slice (v2) -------------------------------------------------------------------- Repeating characters, 128 bytes -🤞 JS with buffering in array (v1) x 1,525,792 ops/sec ±0.18% (98 runs sampled) -🤞 Buffer.prototype.utf8Slice (v2) x 8,600,267 ops/sec ±0.17% (98 runs sampled) -🤞 Buffer.from(arr).slice (v3) x 5,676,294 ops/sec ±0.16% (98 runs sampled) -🤞 Buffer.from(arr).subarray (v4) x 6,014,855 ops/sec ±0.23% (100 runs sampled) -🤞 JS with string concatenation (v5) x 1,612,844 ops/sec ±0.10% (100 runs sampled) -🤞 TextDecoder (v6) x 1,304,084 ops/sec ±1.14% (86 runs sampled) -Fastest is 🤞 Buffer.prototype.utf8Slice (v2) -------------------------------------------------------------------- Repeating characters, 256 bytes -🤞 JS with buffering in array (v1) x 673,037 ops/sec ±0.08% (98 runs sampled) -🤞 Buffer.prototype.utf8Slice (v2) x 7,934,918 ops/sec ±0.26% (99 runs sampled) -🤞 Buffer.from(arr).slice (v3) x 4,803,526 ops/sec ±0.25% (98 runs sampled) -🤞 Buffer.from(arr).subarray (v4) x 5,007,603 ops/sec ±0.27% (94 runs sampled) -🤞 JS with string concatenation (v5) x 816,504 ops/sec ±0.19% (101 runs sampled) -🤞 TextDecoder (v6) x 1,123,970 ops/sec ±0.90% (92 runs sampled) -Fastest is 🤞 Buffer.prototype.utf8Slice (v2) -``` diff --git a/src/util/buffers/utf8/decodeUtf8/__tests__/decodeUtf8.spec.ts b/src/util/buffers/utf8/decodeUtf8/__tests__/decodeUtf8.spec.ts deleted file mode 100644 index 2a74db7bdb..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/__tests__/decodeUtf8.spec.ts +++ /dev/null @@ -1,120 +0,0 @@ -import v1 from '../v1'; -import v2 from '../v2'; -import v3 from '../v3'; -import v4 from '../v4'; -import v5 from '../v5'; -import v6 from '../v6'; -import v7 from '../v7'; -import v8 from '../v8'; -import v9 from '../v9'; -import v10 from '../v10'; -import v11 from '../v11'; -import v12 from '../v12'; -import v13 from '../v13'; -import v14 from '../v14'; -import v15 from '../v15'; -import v16 from '../v16'; -import v17 from '../v17'; -import v18 from '../v18'; -import v19 from '../v19'; - -type Decoder = (buf: Uint8Array, start: number, length: number) => string; - -const runTests = (name: string, decodeUtf8: Decoder) => { - describe(name, () => { - test('can decode basic string', () => { - const arr = new ArrayBuffer(8); - const buf = new Uint8Array(arr); - buf[0] = 1; - buf[1] = 0x61; - buf[2] = 0x62; - buf[3] = 0x63; - buf[4] = 0x64; - buf[5] = 0x65; - buf[6] = 0x66; - buf[7] = 1; - const uint8 = buf.subarray(1, 7); - const str = decodeUtf8(uint8, 1, 2); - expect(str).toBe('bc'); - }); - - test('can decode emoji', () => { - const arr = new ArrayBuffer(8); - const buf = new Uint8Array(arr); - buf[0] = 1; - buf[1] = 0x61; - buf[2] = 0xf0; - buf[3] = 0x9f; - buf[4] = 0x98; - buf[5] = 0x80; - buf[6] = 0x62; - buf[7] = 1; - const uint8 = buf.subarray(1, 7); - const str = decodeUtf8(uint8, 1, 4); - expect(str).toBe('😀'); - }); - - test('can decode a long string', () => { - const str = 'a'.repeat(33333); - const buf = Buffer.from(str); - const arr = new Uint8Array(buf.length); - for (let i = 0; i < arr.length; i++) arr[i] = buf[i]; - const str2 = decodeUtf8(arr, 0, arr.length); - expect(str2).toBe(str); - }); - - test('can decode real-world sentence', () => { - const str = '💯 RëactQuill v2 ReactQuill 2 is here, baby! And it brings a füll port to TypeScript and React 16+.'; - const buf = Buffer.from(str); - const arr = new Uint8Array(buf.length); - for (let i = 0; i < arr.length; i++) arr[i] = buf[i]; - const str2 = decodeUtf8(arr, 0, arr.length); - expect(str2).toBe(str); - }); - - test('can decode various types of characters', () => { - const alphabet = [ - // 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - // 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - // 'u', 'v', 'w', 'x', 'y', 'z', - // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - // 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - // 'U', 'V', 'W', 'X', 'Y', 'Z', - // '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - // '-', '_', '.', ',', ';', '!', '@', '#', '$', '%', - // '^', '&', '*', '\\', '/', '(', ')', '+', '=', '\n', - // '👍', '🏻', '😛', 'ä', 'ö', 'ü', 'ß', 'а', 'б', 'в', - 'г', - '诶', - '必', - '西', - ]; - const str = alphabet.join(''); - const buf = Buffer.from(str); - const arr = new Uint8Array(buf.length); - for (let i = 0; i < arr.length; i++) arr[i] = buf[i]; - const str2 = decodeUtf8(arr, 0, arr.length); - expect(str2).toBe(str); - }); - }); -}; - -runTests('v1', v1); -runTests('v2', v2); -runTests('v3', v3); -runTests('v4', v4); -runTests('v5', v5); -runTests('v6', v6); -runTests('v7', v7); -runTests('v8', v8); -runTests('v9', v9); -runTests('v10', v10); -runTests('v11', v11); -runTests('v12', v12); -runTests('v13', v13); -runTests('v14', v14); -runTests('v15', v15); -runTests('v16', v16); -runTests('v17', v17); -runTests('v18', v18); -runTests('v19', v19); diff --git a/src/util/buffers/utf8/decodeUtf8/index.ts b/src/util/buffers/utf8/decodeUtf8/index.ts deleted file mode 100644 index 7e9349894f..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import decodeUtf8 from './v16'; - -export {decodeUtf8}; diff --git a/src/util/buffers/utf8/decodeUtf8/v1.ts b/src/util/buffers/utf8/decodeUtf8/v1.ts deleted file mode 100644 index d9123022b4..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v1.ts +++ /dev/null @@ -1,38 +0,0 @@ -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - const units: Array = []; - let result = ''; - while (offset < end) { - const byte1 = buf[offset++]!; - if ((byte1 & 0x80) === 0) { - units.push(byte1); - } else if ((byte1 & 0xe0) === 0xc0) { - const byte2 = buf[offset++]! & 0x3f; - units.push(((byte1 & 0x1f) << 6) | byte2); - } else if ((byte1 & 0xf0) === 0xe0) { - const byte2 = buf[offset++]! & 0x3f; - const byte3 = buf[offset++]! & 0x3f; - units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3); - } else if ((byte1 & 0xf8) === 0xf0) { - const byte2 = buf[offset++]! & 0x3f; - const byte3 = buf[offset++]! & 0x3f; - const byte4 = buf[offset++]! & 0x3f; - let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; - if (unit > 0xffff) { - unit -= 0x10000; - units.push(((unit >>> 10) & 0x3ff) | 0xd800); - unit = 0xdc00 | (unit & 0x3ff); - } - units.push(unit); - } else { - units.push(byte1); - } - if (units.length >= 1000) { - result += String.fromCharCode(...units); - units.length = 0; - } - } - if (units.length > 0) result += String.fromCharCode(...units); - return result; -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v10.ts b/src/util/buffers/utf8/decodeUtf8/v10.ts deleted file mode 100644 index ebf8b03d0d..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v10.ts +++ /dev/null @@ -1,39 +0,0 @@ -const fromCharCode = String.fromCharCode; - -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - let str = ''; - while (offset < end) { - const octet1 = buf[offset++]!; - if ((octet1 & 0x80) === 0) { - str += fromCharCode(octet1); - continue; - } - const octet2 = buf[offset++]! & 0x3f; - if ((octet1 & 0xe0) === 0xc0) { - str += fromCharCode(((octet1 & 0x1f) << 6) | octet2); - continue; - } - const octet3 = buf[offset++]! & 0x3f; - if ((octet1 & 0xf0) === 0xe0) { - str += fromCharCode(((octet1 & 0x1f) << 12) | (octet2 << 6) | octet3); - continue; - } - if ((octet1 & 0xf8) === 0xf0) { - const octet4 = buf[offset++]! & 0x3f; - let unit = ((octet1 & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800; - unit = 0xdc00 | (unit & 0x3ff); - str += fromCharCode(unit0, unit); - } else { - str += fromCharCode(unit); - } - } else { - str += fromCharCode(octet1); - } - } - return str; -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v11.ts b/src/util/buffers/utf8/decodeUtf8/v11.ts deleted file mode 100644 index f3beea70cd..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v11.ts +++ /dev/null @@ -1,2 +0,0 @@ -const utf8Slice = Buffer.prototype.utf8Slice; -export default (buf: Uint8Array, start: number, length: number): string => utf8Slice.call(buf, start, start + length); diff --git a/src/util/buffers/utf8/decodeUtf8/v12.ts b/src/util/buffers/utf8/decodeUtf8/v12.ts deleted file mode 100644 index 4a31f6dfc0..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v12.ts +++ /dev/null @@ -1,5 +0,0 @@ -const from = Buffer.from; -export default (arr: Uint8Array, start: number, length: number): string => - from(arr) - .subarray(start, start + length) - .toString(); diff --git a/src/util/buffers/utf8/decodeUtf8/v13.ts b/src/util/buffers/utf8/decodeUtf8/v13.ts deleted file mode 100644 index de26b1dc64..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v13.ts +++ /dev/null @@ -1,27 +0,0 @@ -import v10 from './v10'; - -let decode = v10; - -const hasBuffer = typeof Buffer !== 'undefined'; -const utf8Slice = hasBuffer ? Buffer.prototype.utf8Slice : null; - -if (utf8Slice) { - decode = (buf: Uint8Array, start: number, length: number): string => - length <= 10 ? v10(buf, start, length) : utf8Slice.call(buf, start, start + length); -} else { - const from = hasBuffer ? Buffer.from : null; - if (from) { - decode = (buf: Uint8Array, start: number, length: number): string => - length < 30 - ? v10(buf, start, length) - : from(buf) - .subarray(start, start + length) - .toString(); - } else if (typeof TextDecoder !== 'undefined') { - const decoder = new TextDecoder(); - decode = (buf: Uint8Array, start: number, length: number): string => - length < 150 ? v10(buf, start, length) : decoder.decode(buf.subarray(start, start + length)); - } -} - -export default decode; diff --git a/src/util/buffers/utf8/decodeUtf8/v14.ts b/src/util/buffers/utf8/decodeUtf8/v14.ts deleted file mode 100644 index d9062ad933..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v14.ts +++ /dev/null @@ -1,8 +0,0 @@ -import v10 from './v10'; - -const hasBuffer = typeof Buffer !== 'undefined'; -const utf8Slice = hasBuffer ? Buffer.prototype.utf8Slice : null; - -export default utf8Slice - ? (buf: Uint8Array, start: number, length: number): string => utf8Slice.call(buf, start, start + length) - : v10; diff --git a/src/util/buffers/utf8/decodeUtf8/v15.ts b/src/util/buffers/utf8/decodeUtf8/v15.ts deleted file mode 100644 index b5557c0631..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v15.ts +++ /dev/null @@ -1,16 +0,0 @@ -import v10 from './v10'; - -const hasBuffer = typeof Buffer !== 'undefined'; -const utf8Slice = hasBuffer ? Buffer.prototype.utf8Slice : null; -const from = hasBuffer ? Buffer.from : null; - -export default (buf: Uint8Array, start: number, length: number): string => { - const end = start + length; - return length > 8 - ? utf8Slice - ? utf8Slice.call(buf, start, end) - : from - ? from(buf).subarray(start, end).toString('utf8') - : v10(buf, start, length) - : v10(buf, start, length); -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v16.ts b/src/util/buffers/utf8/decodeUtf8/v16.ts deleted file mode 100644 index c95f699fdc..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v16.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {decodeAscii, decodeAsciiMax15} from '../decodeAscii'; -import v18 from './v18'; - -type Decoder = (buf: Uint8Array, start: number, length: number) => string; - -const hasBuffer = typeof Buffer !== 'undefined'; -const utf8Slice = hasBuffer ? Buffer.prototype.utf8Slice : null; -const from = hasBuffer ? Buffer.from : null; - -const shortDecoder: Decoder = (buf, start, length) => decodeAsciiMax15(buf, start, length) ?? v18(buf, start, length); - -const midDecoder: Decoder = (buf, start, length) => decodeAscii(buf, start, length) ?? v18(buf, start, length); - -const longDecoder: Decoder = utf8Slice - ? (buf, start, length) => utf8Slice.call(buf, start, start + length) - : from - ? (buf, start, length) => - from(buf) - .subarray(start, start + length) - .toString('utf8') - : v18; - -const decoder: Decoder = (buf, start, length): string => { - if (length < 16) return shortDecoder(buf, start, length); - if (length < 32) return midDecoder(buf, start, length); - return longDecoder(buf, start, length); -}; - -export default decoder; diff --git a/src/util/buffers/utf8/decodeUtf8/v17.ts b/src/util/buffers/utf8/decodeUtf8/v17.ts deleted file mode 100644 index 604ac7e022..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v17.ts +++ /dev/null @@ -1,37 +0,0 @@ -const fromCharCode = String.fromCharCode; - -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - let str = ''; - while (offset < end) { - let code = buf[offset++]!; - if ((code & 0x80) !== 0) { - const octet2 = buf[offset++]! & 0x3f; - if ((code & 0xe0) === 0xc0) { - code = ((code & 0x1f) << 6) | octet2; - } else { - const octet3 = buf[offset++]! & 0x3f; - if ((code & 0xf0) === 0xe0) { - code = ((code & 0x1f) << 12) | (octet2 << 6) | octet3; - } else { - if ((code & 0xf8) === 0xf0) { - const octet4 = buf[offset++]! & 0x3f; - let unit = ((code & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800; - unit = 0xdc00 | (unit & 0x3ff); - str += fromCharCode(unit0); - code = unit; - } else { - code = unit; - } - } - } - } - } - str += fromCharCode(code); - } - return str; -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v18.ts b/src/util/buffers/utf8/decodeUtf8/v18.ts deleted file mode 100644 index e1b518e004..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v18.ts +++ /dev/null @@ -1,36 +0,0 @@ -const fromCharCode = String.fromCharCode; - -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - const points: number[] = []; - while (offset < end) { - let code = buf[offset++]!; - if ((code & 0x80) !== 0) { - const octet2 = buf[offset++]! & 0x3f; - if ((code & 0xe0) === 0xc0) { - code = ((code & 0x1f) << 6) | octet2; - } else { - const octet3 = buf[offset++]! & 0x3f; - if ((code & 0xf0) === 0xe0) { - code = ((code & 0x1f) << 12) | (octet2 << 6) | octet3; - } else { - if ((code & 0xf8) === 0xf0) { - const octet4 = buf[offset++]! & 0x3f; - let unit = ((code & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800; - code = 0xdc00 | (unit & 0x3ff); - points.push(unit0); - } else { - code = unit; - } - } - } - } - } - points.push(code); - } - return fromCharCode.apply(String, points); -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v19.ts b/src/util/buffers/utf8/decodeUtf8/v19.ts deleted file mode 100644 index 2bbc39dc2b..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v19.ts +++ /dev/null @@ -1,3 +0,0 @@ -const {readUtf8} = require('json-pack-napi'); - -export default readUtf8; diff --git a/src/util/buffers/utf8/decodeUtf8/v2.ts b/src/util/buffers/utf8/decodeUtf8/v2.ts deleted file mode 100644 index c6612407b9..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v2.ts +++ /dev/null @@ -1,2 +0,0 @@ -export default (buf: Uint8Array, start: number, length: number): string => - Buffer.prototype.utf8Slice.call(buf, start, start + length); diff --git a/src/util/buffers/utf8/decodeUtf8/v3.ts b/src/util/buffers/utf8/decodeUtf8/v3.ts deleted file mode 100644 index fb8adea3ec..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v3.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default (arr: Uint8Array, start: number, length: number): string => - Buffer.from(arr) - .slice(start, start + length) - .toString(); diff --git a/src/util/buffers/utf8/decodeUtf8/v4.ts b/src/util/buffers/utf8/decodeUtf8/v4.ts deleted file mode 100644 index 23b26780c4..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v4.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default (arr: Uint8Array, start: number, length: number): string => - Buffer.from(arr) - .subarray(start, start + length) - .toString(); diff --git a/src/util/buffers/utf8/decodeUtf8/v5.ts b/src/util/buffers/utf8/decodeUtf8/v5.ts deleted file mode 100644 index c00b6ca8ec..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v5.ts +++ /dev/null @@ -1,30 +0,0 @@ -export default (uint8: Uint8Array, start: number, length: number): string => { - const end = start + length; - let x = start; - let str = ''; - while (x < end) { - const b1 = uint8[x++]!; - if ((b1 & 0x80) === 0) { - str += String.fromCharCode(b1); - continue; - } else if ((b1 & 0xe0) === 0xc0) { - str += String.fromCharCode(((b1 & 0x1f) << 6) | (uint8[x++]! & 0x3f)); - } else if ((b1 & 0xf0) === 0xe0) { - str += String.fromCharCode(((b1 & 0x1f) << 12) | ((uint8[x++]! & 0x3f) << 6) | (uint8[x++]! & 0x3f)); - } else if ((b1 & 0xf8) === 0xf0) { - const b2 = uint8[x++]! & 0x3f; - const b3 = uint8[x++]! & 0x3f; - const b4 = uint8[x++]! & 0x3f; - let code = ((b1 & 0x07) << 0x12) | (b2 << 0x0c) | (b3 << 0x06) | b4; - if (code > 0xffff) { - code -= 0x10000; - str += String.fromCharCode(((code >>> 10) & 0x3ff) | 0xd800); - code = 0xdc00 | (code & 0x3ff); - } - str += String.fromCharCode(code); - } else { - str += String.fromCharCode(b1); - } - } - return str; -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v6.ts b/src/util/buffers/utf8/decodeUtf8/v6.ts deleted file mode 100644 index 88acf9be18..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v6.ts +++ /dev/null @@ -1,6 +0,0 @@ -const sharedTextDecoder = new TextDecoder(); - -export default (uint8: Uint8Array, start: number, length: number): string => { - const stringBytes = uint8.subarray(start, start + length); - return sharedTextDecoder.decode(stringBytes); -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v7.ts b/src/util/buffers/utf8/decodeUtf8/v7.ts deleted file mode 100644 index 32ff0da65a..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v7.ts +++ /dev/null @@ -1,32 +0,0 @@ -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - const codes: Array = []; - while (offset < end) { - const octet1 = buf[offset++]!; - if ((octet1 & 0x80) === 0) { - codes.push(octet1); - } else if ((octet1 & 0xe0) === 0xc0) { - const octet2 = buf[offset++]! & 0x3f; - codes.push(((octet1 & 0x1f) << 6) | octet2); - } else if ((octet1 & 0xf0) === 0xe0) { - const octet2 = buf[offset++]! & 0x3f; - const octet3 = buf[offset++]! & 0x3f; - codes.push(((octet1 & 0x1f) << 12) | (octet2 << 6) | octet3); - } else if ((octet1 & 0xf8) === 0xf0) { - const octet2 = buf[offset++]! & 0x3f; - const octet3 = buf[offset++]! & 0x3f; - const octet4 = buf[offset++]! & 0x3f; - let unit = ((octet1 & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - codes.push(((unit >>> 10) & 0x3ff) | 0xd800); - unit = 0xdc00 | (unit & 0x3ff); - } - codes.push(unit); - } else { - codes.push(octet1); - } - } - return String.fromCharCode(...codes); -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v8.ts b/src/util/buffers/utf8/decodeUtf8/v8.ts deleted file mode 100644 index 28b77f6de0..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v8.ts +++ /dev/null @@ -1,39 +0,0 @@ -// String.fromCharCode(...units) flushing happens more often. -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - const units: Array = []; - let result = ''; - while (offset < end) { - const byte1 = buf[offset++]!; - if ((byte1 & 0x80) === 0) { - units.push(byte1); - } else if ((byte1 & 0xe0) === 0xc0) { - const byte2 = buf[offset++]! & 0x3f; - units.push(((byte1 & 0x1f) << 6) | byte2); - } else if ((byte1 & 0xf0) === 0xe0) { - const byte2 = buf[offset++]! & 0x3f; - const byte3 = buf[offset++]! & 0x3f; - units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3); - } else if ((byte1 & 0xf8) === 0xf0) { - const byte2 = buf[offset++]! & 0x3f; - const byte3 = buf[offset++]! & 0x3f; - const byte4 = buf[offset++]! & 0x3f; - let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; - if (unit > 0xffff) { - unit -= 0x10000; - units.push(((unit >>> 10) & 0x3ff) | 0xd800); - unit = 0xdc00 | (unit & 0x3ff); - } - units.push(unit); - } else { - units.push(byte1); - } - if (units.length >= 8) { - result += String.fromCharCode(...units); - units.length = 0; - } - } - if (units.length > 0) result += String.fromCharCode(...units); - return result; -}; diff --git a/src/util/buffers/utf8/decodeUtf8/v9.ts b/src/util/buffers/utf8/decodeUtf8/v9.ts deleted file mode 100644 index 975c03e0f9..0000000000 --- a/src/util/buffers/utf8/decodeUtf8/v9.ts +++ /dev/null @@ -1,35 +0,0 @@ -export default (buf: Uint8Array, start: number, length: number): string => { - let offset = start; - const end = offset + length; - const codes: Array = []; - while (offset < end) { - const octet1 = buf[offset++]!; - if ((octet1 & 0x80) === 0) { - codes.push(octet1); - continue; - } - const octet2 = buf[offset++]! & 0x3f; - if ((octet1 & 0xe0) === 0xc0) { - codes.push(((octet1 & 0x1f) << 6) | octet2); - continue; - } - const octet3 = buf[offset++]! & 0x3f; - if ((octet1 & 0xf0) === 0xe0) { - codes.push(((octet1 & 0x1f) << 12) | (octet2 << 6) | octet3); - continue; - } - if ((octet1 & 0xf8) === 0xf0) { - const octet4 = buf[offset++]! & 0x3f; - let unit = ((octet1 & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4; - if (unit > 0xffff) { - unit -= 0x10000; - codes.push(((unit >>> 10) & 0x3ff) | 0xd800); - unit = 0xdc00 | (unit & 0x3ff); - } - codes.push(unit); - } else { - codes.push(octet1); - } - } - return String.fromCharCode(...codes); -}; diff --git a/src/util/buffers/utf8/encode.ts b/src/util/buffers/utf8/encode.ts deleted file mode 100644 index dedb236782..0000000000 --- a/src/util/buffers/utf8/encode.ts +++ /dev/null @@ -1,58 +0,0 @@ -const hasBuffer = typeof Buffer !== undefined; -const utf8Write = hasBuffer - ? (Buffer.prototype.utf8Write as (this: Uint8Array, str: string, pos: number, maxLength: number) => number) - : null; -const from = hasBuffer ? Buffer.from : null; - -export type EncodeString = (arr: Uint8Array, str: string, pos: number, maxLength: number) => number; - -export const encodeUtf8Write: EncodeString = (arr: Uint8Array, str: string, pos: number, maxLength: number): number => - utf8Write!.call(arr, str, pos, maxLength); - -export const encodeFrom: EncodeString = (arr: Uint8Array, str: string, pos: number, maxLength: number): number => { - const offset = arr.byteOffset + pos; - const buf = from!(arr.buffer).subarray(offset, offset + maxLength); - return buf.write(str, 0, maxLength, 'utf8'); -}; - -export const encodeNative: EncodeString = (arr: Uint8Array, str: string, pos: number, maxLength: number): number => { - const length = str.length; - const start = pos; - let curr = 0; - while (curr < length) { - let value = str.charCodeAt(curr++); - if ((value & 0xffffff80) === 0) { - arr[pos++] = value; - continue; - } else if ((value & 0xfffff800) === 0) { - arr[pos++] = ((value >> 6) & 0x1f) | 0xc0; - } else { - if (value >= 0xd800 && value <= 0xdbff) { - if (curr < length) { - const extra = str.charCodeAt(curr); - if ((extra & 0xfc00) === 0xdc00) { - curr++; - value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; - } - } - } - if ((value & 0xffff0000) === 0) { - arr[pos++] = ((value >> 12) & 0x0f) | 0xe0; - arr[pos++] = ((value >> 6) & 0x3f) | 0x80; - } else { - arr[pos++] = ((value >> 18) & 0x07) | 0xf0; - arr[pos++] = ((value >> 12) & 0x3f) | 0x80; - arr[pos++] = ((value >> 6) & 0x3f) | 0x80; - } - } - arr[pos++] = (value & 0x3f) | 0x80; - } - return pos - start; -}; - -const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null; - -export const encodeTe: EncodeString = (arr: Uint8Array, str: string, pos: number, maxLength: number): number => - textEncoder!.encodeInto(str, arr.subarray(pos, pos + maxLength)).written!; - -export const encode = utf8Write ? encodeUtf8Write : from ? encodeFrom : encodeNative; diff --git a/src/util/buffers/utf8/isUtf8.ts b/src/util/buffers/utf8/isUtf8.ts deleted file mode 100644 index 5b846f0e31..0000000000 --- a/src/util/buffers/utf8/isUtf8.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Validates that the given data is valid UTF-8 text. - * @param buf Data to check. - * @returns True if the data is valid UTF-8. - */ -export const isUtf8 = (buf: Uint8Array, from: number, length: number): boolean => { - const to = from + length; - while (from < to) { - const c = buf[from]; - if (c <= 0x7f) { - from++; - continue; - } - if (c >= 0xc2 && c <= 0xdf) { - if (buf[from + 1] >> 6 === 2) { - from += 2; - continue; - } else return false; - } - const c1 = buf[from + 1]; - if ( - ((c === 0xe0 && c1 >= 0xa0 && c1 <= 0xbf) || (c === 0xed && c1 >= 0x80 && c1 <= 0x9f)) && - buf[from + 2] >> 6 === 2 - ) { - from += 3; - continue; - } - if (((c >= 0xe1 && c <= 0xec) || (c >= 0xee && c <= 0xef)) && c1 >> 6 === 2 && buf[from + 2] >> 6 === 2) { - from += 3; - continue; - } - if ( - ((c === 0xf0 && c1 >= 0x90 && c1 <= 0xbf) || - (c >= 0xf1 && c <= 0xf3 && c1 >> 6 === 2) || - (c === 0xf4 && c1 >= 0x80 && c1 <= 0x8f)) && - buf[from + 2] >> 6 === 2 && - buf[from + 3] >> 6 === 2 - ) { - from += 4; - continue; - } - return false; - } - return true; -}; diff --git a/src/util/buffers/utf8/sharedCachedUtf8Decoder.ts b/src/util/buffers/utf8/sharedCachedUtf8Decoder.ts deleted file mode 100644 index 86b2d4ad03..0000000000 --- a/src/util/buffers/utf8/sharedCachedUtf8Decoder.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {CachedUtf8Decoder} from './CachedUtf8Decoder'; - -export default new CachedUtf8Decoder(); diff --git a/src/util/codegen/Codegen.ts b/src/util/codegen/Codegen.ts deleted file mode 100644 index ab929b1a44..0000000000 --- a/src/util/codegen/Codegen.ts +++ /dev/null @@ -1,296 +0,0 @@ -import {compileClosure} from '.'; -import type {JavaScriptLinked} from './types'; - -/** - * Inline JavaScript statements that are executed in main function body. - */ -export class CodegenStepExecJs { - constructor(public readonly js: string) {} -} - -/** - * A step can be `CodegenStepExecJs` or some application specific step, which - * will later will need to be converted to `CodegenStepExecJs`. - */ -type JsonSerializerStep = CodegenStepExecJs | unknown; - -/** - * Configuration options for {@link Codegen} instances. - */ -export interface CodegenOptions> { - /** - * Inline JavaScript string that represents the arguments that will be passed - * to the main function body. Defaults to "r0", i.e. the first register. - */ - args?: string[]; - - /** - * Name of the generated function. - */ - name?: string; - - /** - * Inline JavaScript statements, that execute at the beginning of the main - * function body. - */ - prologue?: string; - - /** - * Inline JavaScript statements, that execute at the end of the main - * function body. - */ - epilogue?: string | (() => string); - - /** - * Converts all steps to `CodegenStepExecJs`. - */ - processSteps?: (steps: JsonSerializerStep[]) => CodegenStepExecJs[]; - - /** - * Predefined list of dependencies that can be linked on demand. Dependency is - * linked with the name of the property and is linked only once. - */ - linkable?: Linkable; -} - -export type CodegenGenerateOptions = Pick; - -/** - * A helper class which helps with building JavaScript code for a single - * function. It keeps track of external dependencies, internally generated - * constants, and execution steps, which at the end are all converted to - * to an executable JavaScript function. - * - * The final output is a JavaScript function enclosed in a closure: - * - * ```js - * (function(d1, d2, d3) { - * var c1 = something; - * var c2 = something; - * var c3 = something; - * return function(r0) { - * var r1 = something; - * var r2 = something; - * var r3 = something; - * return something; - * } - * }) - * ``` - * - * Where `d*` are the external dependencies, `c*` are the internal constants, - * and `r*` are the local immutable infinite registers. - */ -export class Codegen< - Fn extends (...deps: any[]) => any = (...deps: unknown[]) => unknown, - Linkable = Record, -> { - /** @ignore */ - protected steps: JsonSerializerStep[] = []; - - /** @ignore */ - public options: Required>; - - constructor(opts: CodegenOptions) { - this.options = { - args: ['r0'], - name: '', - prologue: '', - epilogue: '', - processSteps: (steps) => steps.filter((step) => step instanceof CodegenStepExecJs) as CodegenStepExecJs[], - linkable: {} as Linkable, - ...opts, - }; - this.registerCounter = this.options.args.length; - } - - /** - * Add one or more JavaScript statements to the main function body. - */ - public js(js: string): void { - this.steps.push(new CodegenStepExecJs(js)); - } - - public var(expression?: string): string { - const r = this.getRegister(); - if (expression) this.js('var ' + r + ' = ' + expression + ';'); - else this.js('var ' + r + ';'); - return r; - } - - public if(condition: string, then: () => void, otherwise?: () => void): void { - this.js('if (' + condition + ') {'); - then(); - if (otherwise) { - this.js('} else {'); - otherwise(); - } - this.js('}'); - } - - public switch( - expression: string, - cases: [match: string | number | boolean | null, block: () => void, noBreak?: boolean][], - def?: () => void, - ): void { - this.js('switch (' + expression + ') {'); - for (const [match, block, noBreak] of cases) { - this.js('case ' + match + ': {'); - block(); - if (!noBreak) this.js('break;'); - this.js('}'); - } - if (def) { - this.js('default: {'); - def(); - this.js('}'); - } - this.js('}'); - } - - public return(expression: string): void { - this.js('return ' + expression + ';'); - } - - /** - * Add any application specific execution step. Steps of `unknown` type - * later need to converted to `CodegenStepExecJs` steps in the `.processStep` - * callback. - * - * @param step A step in function execution logic. - */ - public step(step: unknown): void { - this.steps.push(step); - } - - protected registerCounter: number; - - /** - * Codegen uses the idea of infinite registers. It starts with `0` and - * increments it by one for each new register. Best practice is to use - * a new register for each new variable and keep them immutable. - * - * Usage: - * - * ```js - * const r = codegen.getRegister(); - * codegen.js(`const ${r} = 1;`); - * ``` - * - * @returns a unique identifier for a variable. - */ - public getRegister(): string { - return `r${this.registerCounter++}`; - } - public r(): string { - return this.getRegister(); - } - - /** @ignore */ - protected dependencies: unknown[] = []; - protected dependencyNames: string[] = []; - - /** - * Allows to wire up dependencies to the generated code. - * - * @param dep Any JavaScript dependency, could be a function, an object, - * or anything else. - * @param name Optional name of the dependency. If not provided, a unique - * name will be generated, which starts with `d` and a counter - * appended. - * @returns Returns the dependency name, a code symbol which can be used as - * variable name. - */ - public linkDependency(dep: unknown, name: string = 'd' + this.dependencies.length): string { - this.dependencies.push(dep); - this.dependencyNames.push(name); - return name; - } - - /** - * Sames as {@link Codegen#linkDependency}, but allows to wire up multiple - * dependencies at once. - */ - public linkDependencies(deps: unknown[]): string[] { - return deps.map((dep) => this.linkDependency(dep)); - } - - protected linked: {[key: string]: 1} = {}; - - /** - * Link a dependency from the pre-defined `options.linkable` object. This method - * can be called many times with the same dependency name, the dependency will - * be linked only once. - * - * @param name Linkable dependency name. - */ - public link(name: keyof Linkable): void { - if (this.linked[name as string]) return; - this.linked[name as string] = 1; - this.linkDependency(this.options.linkable[name], name as string); - } - - /** @ignore */ - protected constants: string[] = []; - protected constantNames: string[] = []; - - /** - * Allows to encode any code or value in the closure of the generated - * function. - * - * @param constant Any JavaScript value in string form. - * @param name Optional name of the constant. If not provided, a unique - * name will be generated, which starts with `c` and a counter - * appended. - * @returns Returns the constant name, a code symbol which can be used as - * variable name. - */ - public addConstant(constant: string, name: string = 'c' + this.constants.length): string { - this.constants.push(constant); - this.constantNames.push(name); - return name; - } - - /** - * Sames as {@link Codegen#addConstant}, but allows to create multiple - * constants at once. - */ - public addConstants(constants: string[]): string[] { - return constants.map((constant) => this.addConstant(constant)); - } - - /** - * Returns generated JavaScript code with the dependency list. - * - * ```js - * const code = codegen.generate(); - * const fn = eval(code.js)(...code.deps); - * const result = fn(...args); - * ``` - */ - public generate(opts: CodegenGenerateOptions = {}): JavaScriptLinked { - const {name, args, prologue, epilogue} = {...this.options, ...opts}; - const steps = this.options.processSteps(this.steps); - const js = `(function(${this.dependencyNames.join(', ')}) { -${this.constants.map((constant, index) => `var ${this.constantNames[index]} = (${constant});`).join('\n')} -return ${name ? `function ${name}` : 'function'}(${args.join(',')}){ -${prologue} -${steps.map((step) => (step as CodegenStepExecJs).js).join('\n')} -${typeof epilogue === 'function' ? epilogue() : epilogue || ''} -}})`; - // console.log(js); - return { - deps: this.dependencies, - js: js as JavaScriptLinked['js'], - }; - } - - /** - * Compiles the generated JavaScript code into a function. - * - * @returns JavaScript function ready for execution. - */ - public compile(opts?: CodegenGenerateOptions): Fn { - const closure = this.generate(opts); - return compileClosure(closure); - } -} diff --git a/src/util/codegen/README.md b/src/util/codegen/README.md deleted file mode 100644 index 5a3951e1af..0000000000 --- a/src/util/codegen/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# util/codegen - -This folder contains utilities for generating code. It is sometimes possible to -generate an optimized function that will execute significantly faster given -a "schema", or "template", of execution. - -Some examples: - -- Deep equality comparison function: if we know one object in advance we can - generate an optimized function which accepts a single object. It is - implemented in `json-equal` library. -- JSON Patch execution: if we know the JSON Patch in advance, we can generate - an optimized function which applies the JSON patch in the most efficient way. - It is implemented in `json-patch` library. -- Given a `json-type` schema of a JSON object, it is possible to generate - optimized functions for validation and serialization of objects according to - that schema. diff --git a/src/util/codegen/__tests__/Codegen.spec.ts b/src/util/codegen/__tests__/Codegen.spec.ts deleted file mode 100644 index 4183da60e5..0000000000 --- a/src/util/codegen/__tests__/Codegen.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {CodegenStepExecJs} from '..'; -import {Codegen} from '../Codegen'; - -test('can generate a simple function', () => { - const codegen = new Codegen({ - name: 'foobar', - args: ['a', 'b'], - prologue: 'var res = 0;', - epilogue: 'return res;', - processSteps: (steps) => { - return steps.map((step) => { - if (typeof step === 'number') { - return new CodegenStepExecJs(`a += ${step};`); - } else return step; - }) as CodegenStepExecJs[]; - }, - }); - codegen.step(4); - const [c1, c2] = codegen.addConstants(['1', '2']); - codegen.js(`b += ${c1} + ${c2};`); - const byTwo = (num: number) => 2 * num; - codegen.linkDependency(byTwo, 'byTwo'); - codegen.js(`res += byTwo(a) + byTwo(b);`); - const code = codegen.generate(); - const fn = codegen.compile(); - // console.log(code.js); - expect(code.deps).toStrictEqual([byTwo]); - expect(typeof code.js).toBe('string'); - expect(fn(1, 2)).toBe(20); - expect(fn.name).toBe('foobar'); -}); diff --git a/src/util/codegen/compile.ts b/src/util/codegen/compile.ts deleted file mode 100644 index a1c0bbbbe2..0000000000 --- a/src/util/codegen/compile.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {JavaScriptLinked} from '.'; -import {JavaScript} from './types'; - -// tslint:disable-next-line -export const compile = (js: JavaScript): T => eval(js); - -export const compileClosure = (fn: JavaScriptLinked): T => compile(fn.js)(...fn.deps); diff --git a/src/util/codegen/dynamicFunction.ts b/src/util/codegen/dynamicFunction.ts deleted file mode 100644 index 38a622a0b7..0000000000 --- a/src/util/codegen/dynamicFunction.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Wraps a function into a proxy function with the same signature, but which can - * be re-implemented by the user at runtime. - * - * @param implementation Initial implementation. - * @returns Proxy function and implementation setter. - */ -export const dynamicFunction = any>( - implementation: F, -): [fn: F, set: (fn: F) => void] => { - const proxy = ((...args) => implementation(...args)) as F; - const set = (f: F) => { - implementation = f; - }; - return [proxy, set]; -}; diff --git a/src/util/codegen/index.ts b/src/util/codegen/index.ts index 3a96aef3c2..41fa667fe6 100644 --- a/src/util/codegen/index.ts +++ b/src/util/codegen/index.ts @@ -1,3 +1 @@ -export * from './types'; -export * from './compile'; -export * from './Codegen'; +export * from '@jsonjoy.com/json-pack/lib/util/codegen'; diff --git a/src/util/codegen/switch.ts b/src/util/codegen/switch.ts deleted file mode 100644 index 3c98a124fc..0000000000 --- a/src/util/codegen/switch.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {dynamicFunction} from './dynamicFunction'; - -/** - * Switcher for code generation. It first executes "evaluation" function - * 3 times, and then generates optimized code. - */ -export const createSwitch = any>(fn: F, codegen: () => F): F => { - let counter = 0; - const [proxy, set] = dynamicFunction((...args) => { - if (counter > 2) set(codegen()); - counter++; - return fn(...args); - }); - return proxy as F; -}; diff --git a/src/util/codegen/types.ts b/src/util/codegen/types.ts deleted file mode 100644 index b9bcd8a44f..0000000000 --- a/src/util/codegen/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type {Brand} from '../types'; - -/** - * Represents a string which contains JavaScript code, which can be - * executed by the `eval` function. - * - * ```ts - * const code: JavaScript<() => {}> = `() => {}`; - * const fn = eval(code); // () => {} - * ``` - */ -export type JavaScript = Brand; - -/** - * Represents a string which contains JavaScript code, which is enclosed - * in a JavaScript closure function. The dependencies can be "linked" to - * the JavaScript code, by executing the outer closure function with the - * list of dependencies as arguments. - * - * ```ts - * const multBy: JavaScriptClosure<(x: number) => number, [by: number]> = - * 'function(by) { return function (x) { return x * by }}'; - * - * const multBy3 = eval(multBy)(3); - * - * multBy3(5); // 15 - * ``` - */ -export type JavaScriptClosure = JavaScript<(...deps: D) => Js>; - -/** - * Represents a {@link JavaScriptClosure} with a fixed list of dependencies, - * that can be linked to the JavaScript code-generated closure. - */ -export interface JavaScriptLinked { - deps: Dependencies; - js: JavaScriptClosure; -} diff --git a/src/util/codegen/util/JsExpression.ts b/src/util/codegen/util/JsExpression.ts deleted file mode 100644 index 7ddbd4e604..0000000000 --- a/src/util/codegen/util/JsExpression.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * JsExpression monad allows to write JS expression as strings which depend on each - * other and tracks whether an expression was used or not. - * - * ```ts - * const expr = new JsExpression(() => 'r0'); - * const subExpr = expr.chain((expr) => `${expr}["key"]`); - * - * expr.wasUsed; // false - * subExpr.use(); // r0["key"] - * expr.wasUsed; // true - * subExpr.wasUsed; // true - * ``` - */ -export class JsExpression { - private _wasUsed: boolean = false; - private _expression?: string; - private _listeners: ((expr: string) => void)[] = []; - - constructor(private expression: () => string) {} - - public get wasUsed(): boolean { - return this._wasUsed; - } - - public use(): string { - if (this._wasUsed) return this._expression!; - this._wasUsed = true; - const expression = (this._expression = this.expression()); - for (const listener of this._listeners) listener(expression); - return expression; - } - - public chain(use: (expr: string) => string): JsExpression { - return new JsExpression(() => use(this.use())); - } - - public addListener(listener: (expr: string) => void): void { - this._listeners.push(listener); - } -} diff --git a/src/util/codegen/util/helpers.ts b/src/util/codegen/util/helpers.ts deleted file mode 100644 index 8558b290da..0000000000 --- a/src/util/codegen/util/helpers.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const emitStringMatch = (expression: string, offset: string, match: string) => { - const conditions: string[] = []; - for (let i = 0; i < match.length; i++) - conditions.push(`${match.charCodeAt(i)} === ${expression}.charCodeAt(${offset} + ${i})`); - return conditions.join(' && '); -}; diff --git a/src/util/codegen/util/normalizeAccessor.ts b/src/util/codegen/util/normalizeAccessor.ts deleted file mode 100644 index 8bfa283fb7..0000000000 --- a/src/util/codegen/util/normalizeAccessor.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const normalizeAccessor = (accessor: string): string => { - if (/^[a-z_][a-z_0-9]*$/i.test(accessor)) { - return '.' + accessor; - } else { - return `[${JSON.stringify(accessor)}]`; - } -}; diff --git a/src/util/router/codegen.ts b/src/util/router/codegen.ts index cff9b898f8..96e516fca3 100644 --- a/src/util/router/codegen.ts +++ b/src/util/router/codegen.ts @@ -1,5 +1,5 @@ -import {Codegen} from '../codegen'; -import {JsExpression} from '../codegen/util/JsExpression'; +import {Codegen} from '@jsonjoy.com/json-pack/lib/util/codegen'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import type {Match} from './router'; export type RouteMatcher = (route: string) => undefined | Match; diff --git a/src/util/router/router.ts b/src/util/router/router.ts index 5ffaf74023..6b0daee5d0 100644 --- a/src/util/router/router.ts +++ b/src/util/router/router.ts @@ -1,4 +1,4 @@ -import {JsExpression} from '../codegen/util/JsExpression'; +import {JsExpression} from '@jsonjoy.com/json-pack/lib/util/codegen/util/JsExpression'; import {printTree} from '../print/printTree'; import {Printable} from '../print/types'; import {RouteMatcher, RouterCodegenCtx, RouterCodegenOpts} from './codegen'; diff --git a/src/util/router/tree.ts b/src/util/router/tree.ts index b6ea5b49ae..d32484a128 100644 --- a/src/util/router/tree.ts +++ b/src/util/router/tree.ts @@ -1,4 +1,4 @@ -import {emitStringMatch} from '../codegen/util/helpers'; +import {emitStringMatch} from '@jsonjoy.com/json-pack/lib/util/codegen/util/helpers'; import {printTree} from '../print/printTree'; import {Printable} from '../print/types'; import {RadixTree} from '../trees/radix/RadixTree'; diff --git a/src/util/sort/insertion.ts b/src/util/sort/insertion.ts index ff12dfb289..69d45d86c7 100644 --- a/src/util/sort/insertion.ts +++ b/src/util/sort/insertion.ts @@ -1,21 +1 @@ -/** - * Insertion sort, should be faster than built-int sort for small arrays. - * - * @todo Move this to `thingies` package. - * - * @param arr Array to sort. - * @returns Returns the same array instance. - */ -export const sort = (arr: T[]): T[] => { - const length = arr.length; - for (let i = 1; i < length; i++) { - const currentValue = arr[i]; - let position = i; - while (position !== 0 && arr[position - 1] > currentValue) { - arr[position] = arr[position - 1]; - position--; - } - arr[position] = currentValue; - } - return arr; -}; +export * from '@jsonjoy.com/json-pack/lib/util/sort/insertion'; diff --git a/src/util/sort/insertion2.ts b/src/util/sort/insertion2.ts index 8525b7e350..dbf23491f1 100644 --- a/src/util/sort/insertion2.ts +++ b/src/util/sort/insertion2.ts @@ -1,22 +1 @@ -/** - * Insertion sort, should be faster than built-int sort for small arrays. - * - * @todo Move this to `thingies` package. - * - * @param arr Array to sort. - * @param comparator Comparator function. - * @returns Returns the same array instance. - */ -export const sort = (arr: T[], comparator: (a: T, b: T) => number): T[] => { - const length = arr.length; - for (let i = 1; i < length; i++) { - const currentValue = arr[i]; - let position = i; - while (position !== 0 && comparator(arr[position - 1], currentValue) > 0) { - arr[position] = arr[position - 1]; - position--; - } - arr[position] = currentValue; - } - return arr; -}; +export * from '@jsonjoy.com/json-pack/lib/util/sort/insertion2'; diff --git a/src/util/strings/__tests__/asString.spec.ts b/src/util/strings/__tests__/asString.spec.ts deleted file mode 100644 index 80d924eb8e..0000000000 --- a/src/util/strings/__tests__/asString.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {asString} from '../asString'; - -const check = (str: string) => { - expect(asString(str)).toBe(JSON.stringify(str)); - expect(JSON.parse(asString(str))).toBe(str); -}; - -const generateStr = (): string => { - let str = ''; - for (let i = 0; i < 5; i++) str += String.fromCodePoint(Math.round(Math.random() * 0x6ffff)); - return str; -}; - -test('encodes the same as JSON.stringify()', () => { - check(''); - check('"'); - check("'"); - check('asdf'); - check('asdfasdfasdfasdfsadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfsadfasdfasdfasdf'); - check('🍻'); - check('👩‍👩‍👦‍👦'); - check('Лексилогос'); - check('\b'); - check('\b\t\0'); - check('\0'); - check('\f'); - check('\r'); - check('\n'); -}); - -test('encodes the same as JSON.stringify(), autogenerated', () => { - for (let i = 0; i < 10000; i++) check(generateStr()); -}); diff --git a/src/util/strings/__tests__/utf8.spec.ts b/src/util/strings/__tests__/utf8.spec.ts deleted file mode 100644 index 9bbdaf5783..0000000000 --- a/src/util/strings/__tests__/utf8.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {utf8Size} from '../utf8'; - -describe('utf8Size', () => { - describe('computes correct size', () => { - const check = (str: string) => { - expect(utf8Size(str)).toBe(Buffer.from(str).byteLength); - }; - - test('encodes the same as JSON.stringify()', () => { - check(''); - check('"'); - check("'"); - check('asdf'); - check('asdfasdfasdfasdfsadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfsadfasdfasdfasdf'); - check('🍻'); - check('👩‍👩‍👦‍👦'); - check('Лексилогос'); - check('\b'); - check('\b\t\0'); - check('\0'); - check('\f'); - check('\r'); - check('\n'); - }); - }); -}); diff --git a/src/util/strings/__tests__/util.spec.ts b/src/util/strings/__tests__/util.spec.ts deleted file mode 100644 index 2ae776bdf1..0000000000 --- a/src/util/strings/__tests__/util.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {isLetter, isPunctuation, isWhitespace} from '../util'; - -describe('isLetter()', () => { - it('should return true for letters', () => { - expect(isLetter('a')).toBe(true); - expect(isLetter('z')).toBe(true); - expect(isLetter('æ')).toBe(true); - expect(isLetter('б')).toBe(true); - expect(isLetter('A')).toBe(true); - }); - - it('should return true for numbers', () => { - expect(isLetter('0')).toBe(true); - expect(isLetter('1')).toBe(true); - expect(isLetter('9')).toBe(true); - }); - - it('should return false for non-letters', () => { - expect(isLetter('!')).toBe(false); - expect(isLetter(' ')).toBe(false); - expect(isLetter(' ')).toBe(false); - }); -}); - -describe('isPunctuation()', () => { - it('should return true for punctuation', () => { - expect(isPunctuation('.')).toBe(true); - expect(isPunctuation(',')).toBe(true); - expect(isPunctuation('?')).toBe(true); - expect(isPunctuation('!')).toBe(true); - expect(isPunctuation('…')).toBe(true); - }); - - it('should return false for non-punctuation', () => { - expect(isPunctuation('a')).toBe(false); - expect(isPunctuation('1')).toBe(false); - expect(isPunctuation(' ')).toBe(false); - }); -}); - -describe('isWhitespace()', () => { - it('should return true for whitespace', () => { - expect(isWhitespace(' ')).toBe(true); - expect(isWhitespace('\t')).toBe(true); - expect(isWhitespace('\n')).toBe(true); - expect(isWhitespace('\r')).toBe(true); - }); - - it('should return false for non-whitespace', () => { - expect(isWhitespace('a')).toBe(false); - expect(isWhitespace('1')).toBe(false); - expect(isWhitespace('.')).toBe(false); - }); -}); diff --git a/src/util/strings/__tests__/wordWrap.spec.ts b/src/util/strings/__tests__/wordWrap.spec.ts deleted file mode 100644 index c19d576740..0000000000 --- a/src/util/strings/__tests__/wordWrap.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {wordWrap} from '../wordWrap'; - -test('does not format a short line', () => { - expect(wordWrap('Hello')).toStrictEqual(['Hello']); -}); - -const text = - 'Acclaimed Harvard professor and entrepreneur Dr. David Sinclair believes that we will see human life expectancy increase to at least 100 years within this century. A world in which humans live significantly longer will have a major impact on economies, policies, healthcare, education, ethics, and more. Sinclair joined Bridgewater Portfolio Strategist Atul Lele to discuss the science and societal, political, systemic and ethical implications of humans living significantly longer lives.'; - -test('wraps long text', () => { - const result = wordWrap(text); - expect(result).toMatchInlineSnapshot(` - [ - "Acclaimed Harvard professor and entrepreneur Dr. ", - "David Sinclair believes that we will see human ", - "life expectancy increase to at least 100 years ", - "within this century. A world in which humans live ", - "significantly longer will have a major impact on ", - "economies, policies, healthcare, education, ", - "ethics, and more. Sinclair joined Bridgewater ", - "Portfolio Strategist Atul Lele to discuss the ", - "science and societal, political, systemic and ", - "ethical implications of humans living ", - "significantly longer lives.", - ] - `); -}); - -test('can specify line width', () => { - const result = wordWrap(text, {width: 80}); - expect(result).toMatchInlineSnapshot(` - [ - "Acclaimed Harvard professor and entrepreneur Dr. David Sinclair believes that we ", - "will see human life expectancy increase to at least 100 years within this ", - "century. A world in which humans live significantly longer will have a major ", - "impact on economies, policies, healthcare, education, ethics, and more. Sinclair ", - "joined Bridgewater Portfolio Strategist Atul Lele to discuss the science and ", - "societal, political, systemic and ethical implications of humans living ", - "significantly longer lives.", - ] - `); -}); diff --git a/src/util/strings/asString.ts b/src/util/strings/asString.ts deleted file mode 100644 index 34de018ea1..0000000000 --- a/src/util/strings/asString.ts +++ /dev/null @@ -1,22 +0,0 @@ -const stringify = JSON.stringify; - -/** Serialize text as a JSON string value. */ -export const asString = (str: string) => { - const length = str.length; - if (length > 41) return stringify(str); - let result = ''; - let last = 0; - let found = false; - let point = 255; - for (let i = 0; i < length && point >= 32; i++) { - point = str.charCodeAt(i); - if (point >= 0xd800 && point <= 0xdfff) return stringify(str); - if (point === 34 || point === 92) { - result += str.slice(last, i) + '\\'; - last = i; - found = true; - } - } - if (point < 32) return stringify(str); - return '"' + (!found ? str : result + str.slice(last)) + '"'; -}; diff --git a/src/util/strings/escape.ts b/src/util/strings/escape.ts deleted file mode 100644 index ad3d60ef7b..0000000000 --- a/src/util/strings/escape.ts +++ /dev/null @@ -1,134 +0,0 @@ -// License: https://github.com/BridgeAR/safe-stable-stringify/blob/78891ff37c6e8936118b8fa47ed59dd761c3208a/LICENSE - -const strEscapeSequencesRegExp = - /[\u0000-\u001f\u0022\u005c\ud800-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(?:[^\ud800-\udbff]|^)[\udc00-\udfff]/; -const strEscapeSequencesReplacer = - /[\u0000-\u001f\u0022\u005c\ud800-\udfff]|[\ud800-\udbff](?![\udc00-\udfff])|(?:[^\ud800-\udbff]|^)[\udc00-\udfff]/g; -const meta = [ - '\\u0000', - '\\u0001', - '\\u0002', - '\\u0003', - '\\u0004', - '\\u0005', - '\\u0006', - '\\u0007', - '\\b', - '\\t', - '\\n', - '\\u000b', - '\\f', - '\\r', - '\\u000e', - '\\u000f', - '\\u0010', - '\\u0011', - '\\u0012', - '\\u0013', - '\\u0014', - '\\u0015', - '\\u0016', - '\\u0017', - '\\u0018', - '\\u0019', - '\\u001a', - '\\u001b', - '\\u001c', - '\\u001d', - '\\u001e', - '\\u001f', - '', - '', - '\\"', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '', - '\\\\', -]; - -const esc_ = (str: string): string => { - if (str.length === 2) return str[0] + '\\u' + str.charCodeAt(1).toString(16); - const charCode = str.charCodeAt(0); - return meta.length > charCode ? meta[charCode] : '\\u' + charCode.toString(16); -}; - -export const escape = (str: string): string => { - let point, - last = 0, - result = ''; - if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) return str; - if (str.length > 100) return str.replace(strEscapeSequencesReplacer, esc_); - for (let i = 0; i < str.length; i++) { - point = str.charCodeAt(i); - if (point === 34 || point === 92 || point < 32) { - result += str.slice(last, i) + meta[point]; - last = i + 1; - } else if (point >= 0xd800 && point <= 0xdfff) { - if (point <= 0xdbff && i + 1 < str.length) { - point = str.charCodeAt(i + 1); - if (point >= 0xdc00 && point <= 0xdfff) { - i++; - continue; - } - } - result += str.slice(last, i) + '\\u' + point.toString(16); - last = i + 1; - } - } - result += str.slice(last); - return result; -}; diff --git a/src/util/strings/flatstr.ts b/src/util/strings/flatstr.ts deleted file mode 100644 index 1479ac271a..0000000000 --- a/src/util/strings/flatstr.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const flatstr = (s: string): string => { - (s) | 0; - Number(s); - return s; -}; diff --git a/src/util/strings/utf8.ts b/src/util/strings/utf8.ts deleted file mode 100644 index 9631bb33b4..0000000000 --- a/src/util/strings/utf8.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Given a JavaScript string, computes how many bytes it will take to encode - * that string in UTF-8. - * - * @param str JavaScript string. - * @returns Length in bytes if encoded as UTF-8. - */ -export function utf8Size(str: string): number { - const length = str.length; - let size = 0; - let pos = 0; - while (pos < length) { - let value = str.charCodeAt(pos++); - if ((value & 0xffffff80) === 0) { - size++; - continue; - } else if ((value & 0xfffff800) === 0) size += 2; - else { - if (value >= 0xd800 && value <= 0xdbff && pos < length) { - const extra = str.charCodeAt(pos); - if ((extra & 0xfc00) === 0xdc00) value = (pos++, ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000); - } - size += 3 + +((value & 0xffff0000) !== 0); - } - } - return size; -} diff --git a/src/util/strings/util.ts b/src/util/strings/util.ts deleted file mode 100644 index a75f5804f5..0000000000 --- a/src/util/strings/util.ts +++ /dev/null @@ -1,8 +0,0 @@ -const LETTER_REGEX = /(\p{Letter}|\d)/u; -const WHITESPACE_REGEX = /\s/; - -export type CharPredicate = (char: string) => boolean; - -export const isLetter: CharPredicate = (char: string) => LETTER_REGEX.test(char[0]); -export const isWhitespace: CharPredicate = (char: string) => WHITESPACE_REGEX.test(char[0]); -export const isPunctuation: CharPredicate = (char: string) => !isLetter(char) && !isWhitespace(char); diff --git a/src/util/strings/wordWrap.ts b/src/util/strings/wordWrap.ts deleted file mode 100644 index ab6b61aee2..0000000000 --- a/src/util/strings/wordWrap.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface WrapOptions { - width?: number; -} - -const lineMap = (line: string) => - line.slice(-1) === '\n' ? line.slice(0, line.length - 1).replace(/[ \t]*$/gm, '') : line; -const lineReduce = (acc: string[], line: string) => { - acc.push(...line.split('\n')); - return acc; -}; - -export const wordWrap = (str: string, options: WrapOptions = {}): string[] => { - if (!str) return []; - - const width = options.width || 50; - const regexString = '.{1,' + width + '}([\\s\u200B]+|$)|[^\\s\u200B]+?([\\s\u200B]+|$)'; - const re = new RegExp(regexString, 'g'); - const lines = (str.match(re) || []).map(lineMap).reduce(lineReduce, [] as string[]); - - return lines; -}; diff --git a/src/web3/adl/hamt-crdt/Hamt.ts b/src/web3/adl/hamt-crdt/Hamt.ts index 1097349c54..98992c9022 100644 --- a/src/web3/adl/hamt-crdt/Hamt.ts +++ b/src/web3/adl/hamt-crdt/Hamt.ts @@ -4,7 +4,7 @@ import {HamtFrame} from './HamtFrame'; import * as hlc from '../../hlc'; import {Cid} from '../../multiformats'; import {sha256} from '../../crypto'; -import {toBuf} from '../../../util/buffers/toBuf'; +import {toBuf} from '@jsonjoy.com/json-pack/lib/util/buffers/toBuf'; import type {CidCasStruct} from '../../store/cas/CidCasStruct'; import type * as types from './types'; diff --git a/src/web3/adl/hamt-crdt/HamtFrame.ts b/src/web3/adl/hamt-crdt/HamtFrame.ts index d7db93f788..87cab2b8b4 100644 --- a/src/web3/adl/hamt-crdt/HamtFrame.ts +++ b/src/web3/adl/hamt-crdt/HamtFrame.ts @@ -1,5 +1,5 @@ import {Defer} from 'thingies/es2020/Defer'; -import {cmpUint8Array2} from '../../../util/buffers/cmpUint8Array2'; +import {cmpUint8Array2} from '@jsonjoy.com/json-pack/lib/util/buffers/cmpUint8Array2'; import {cmpDto} from '../../hlc'; import {CidCasStruct} from '../../store/cas/CidCasStruct'; import {Cid} from '../../multiformats'; diff --git a/src/web3/adl/hamt-crdt/__tests__/Hamt.spec.ts b/src/web3/adl/hamt-crdt/__tests__/Hamt.spec.ts index 0fb09c947d..b52311c47b 100644 --- a/src/web3/adl/hamt-crdt/__tests__/Hamt.spec.ts +++ b/src/web3/adl/hamt-crdt/__tests__/Hamt.spec.ts @@ -1,4 +1,4 @@ -import {b} from '../../../../util/buffers/b'; +import {b} from '@jsonjoy.com/json-pack/lib/util/buffers/b'; import {HlcFactory} from '../../../hlc'; import {CidCasMemory} from '../../../store/cas/CidCasMemory'; import {CidCasStructCbor} from '../../../store/cas/CidCasStructCbor'; diff --git a/src/web3/codec/codecs/cbor.ts b/src/web3/codec/codecs/cbor.ts index b5a6dbdcf4..96f18fc171 100644 --- a/src/web3/codec/codecs/cbor.ts +++ b/src/web3/codec/codecs/cbor.ts @@ -1,5 +1,5 @@ -import {CborEncoderDag} from '../../../json-pack/cbor/CborEncoderDag'; -import {CborDecoderDag} from '../../../json-pack/cbor/CborDecoderDag'; +import {CborEncoderDag} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoderDag'; +import {CborDecoderDag} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderDag'; import {Cid} from '../../multiformats'; import {writer} from './writer'; import type {IpldCodec} from '../types'; diff --git a/src/web3/codec/codecs/writer.ts b/src/web3/codec/codecs/writer.ts index fd58d8bb9f..195e12d84c 100644 --- a/src/web3/codec/codecs/writer.ts +++ b/src/web3/codec/codecs/writer.ts @@ -1,3 +1,3 @@ -import {Writer} from '../../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; export const writer = new Writer(); diff --git a/src/web3/codec/types.ts b/src/web3/codec/types.ts index c02c6ae304..8c72eaf954 100644 --- a/src/web3/codec/types.ts +++ b/src/web3/codec/types.ts @@ -1,4 +1,4 @@ -import type {BinaryJsonDecoder, BinaryJsonEncoder} from '../../json-pack/types'; +import type {BinaryJsonDecoder, BinaryJsonEncoder} from '@jsonjoy.com/json-pack/lib/types'; export interface IpldCodec { name: string; diff --git a/src/web3/multiformats/Multihash.ts b/src/web3/multiformats/Multihash.ts index 30afd81bfb..d6ef9af470 100644 --- a/src/web3/multiformats/Multihash.ts +++ b/src/web3/multiformats/Multihash.ts @@ -1,4 +1,4 @@ -import {cmpUint8Array} from '../../util/buffers/cmpUint8Array'; +import {cmpUint8Array} from '@jsonjoy.com/json-pack/lib/util/buffers/cmpUint8Array'; import {crypto} from '../crypto'; import * as uvint from '../util/uvint'; import {Multicodec} from './constants'; diff --git a/tsconfig.json b/tsconfig.json index dd0384430b..6da30a9f98 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,7 +39,6 @@ ], "typedocOptions": { "entryPoints": [ - "src/binary-rx/index.ts", "src/json-crdt/index.ts", "src/json-crdt/codec/structural/binary/index.ts", "src/json-crdt/codec/structural/compact/index.ts", diff --git a/yarn.lock b/yarn.lock index 52025ca36a..d3e099929b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -670,6 +670,20 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsonjoy.com/base64@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.1.tgz#a717fd8840f7bad49c7fe66cc65db8bcfc4c4dc5" + integrity sha512-LnFjVChaGY8cZVMwAIMjvA1XwQjZ/zIXHyh28IyJkyNkzof4Dkm1+KN9UIm3lHhREH4vs7XwZ0NpkZKnwOtEfg== + +"@jsonjoy.com/json-pack@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-1.0.1.tgz#ab324209c99d1b0ccf7a247ce81a45658ec31283" + integrity sha512-a8nau3pCEmoyCR3O3ih5XVxhFhs1+PPphNAbTN1P66TOvPItWQ9NyGE78Rc8YgoyWBPwwyGW1C60sS8/Ji3L8g== + dependencies: + "@jsonjoy.com/base64" "^1.1.1" + hyperdyperid "^1.2.0" + thingies "^1.20.0" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" From b0272d9ec08e521d455d5c4a963a7ea10b95c757 Mon Sep 17 00:00:00 2001 From: streamich Date: Tue, 9 Apr 2024 19:39:45 +0200 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=F0=9F=A4=96=20fix=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/msgpack-documents.ts | 4 ++-- src/json-crdt-patch/__bench__/bench.encoding.ts | 2 +- src/json-crdt/__bench__/bench.codecs.decoding.ts | 4 ++-- src/json-crdt/__bench__/bench.codecs.encoding.ts | 2 +- src/json-crdt/__bench__/bench.json.encoding.ts | 2 +- src/json-crdt/__bench__/util/structural-editors.ts | 4 ++-- src/json-crdt/__tests__/fuzzer/generate-trace.ts | 4 ++-- src/json-size/__bench__/json-size.ts | 2 +- src/json-type/__bench__/encode.ts | 8 ++++---- src/server/__bench__/ping.bench.ts | 6 +++--- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/__tests__/msgpack-documents.ts b/src/__tests__/msgpack-documents.ts index a2f1260905..4cad435e7b 100644 --- a/src/__tests__/msgpack-documents.ts +++ b/src/__tests__/msgpack-documents.ts @@ -1,5 +1,5 @@ -import {JsonPackExtension, JsonPackValue} from '../json-pack/msgpack'; -import {encodeFull} from '../json-pack/msgpack/util'; +import {JsonPackExtension, JsonPackValue} from '@jsonjoy.com/json-pack/lib/msgpack'; +import {encodeFull} from '@jsonjoy.com/json-pack/lib/msgpack/util'; export interface JsonDocument { name: string; diff --git a/src/json-crdt-patch/__bench__/bench.encoding.ts b/src/json-crdt-patch/__bench__/bench.encoding.ts index ca782387c6..23daf72e19 100644 --- a/src/json-crdt-patch/__bench__/bench.encoding.ts +++ b/src/json-crdt-patch/__bench__/bench.encoding.ts @@ -9,7 +9,7 @@ import {PatchBuilder} from '../PatchBuilder'; import {encode as encodeBinary} from '../codec/binary'; import {encode as encodeCompact} from '../codec/compact-binary'; import {encode as encodeJson} from '../codec/verbose'; -import {encode as encodeCbor} from '../../json-pack/cbor/shared'; +import {encode as encodeCbor} from '@jsonjoy.com/json-pack/lib/cbor/shared'; const createPatch = (json: any) => { const clock = new LogicalClock(123456, 0); diff --git a/src/json-crdt/__bench__/bench.codecs.decoding.ts b/src/json-crdt/__bench__/bench.codecs.decoding.ts index d2dd26ac47..8e03d052e0 100644 --- a/src/json-crdt/__bench__/bench.codecs.decoding.ts +++ b/src/json-crdt/__bench__/bench.codecs.decoding.ts @@ -10,8 +10,8 @@ import {Encoder as IndexedEncoder} from '../codec/indexed/binary/Encoder'; import {Decoder as IndexedDecoder} from '../codec/indexed/binary/Decoder'; import {Encoder as SidecarEncoder} from '../codec/sidecar/binary/Encoder'; import {Decoder as SidecarDecoder} from '../codec/sidecar/binary/Decoder'; -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; -import {CborDecoder} from '../../json-pack/cbor/CborDecoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; import {Model} from '../model'; const cborEncoder = new CborEncoder(); diff --git a/src/json-crdt/__bench__/bench.codecs.encoding.ts b/src/json-crdt/__bench__/bench.codecs.encoding.ts index 0770575c3c..18bdc5d7a5 100644 --- a/src/json-crdt/__bench__/bench.codecs.encoding.ts +++ b/src/json-crdt/__bench__/bench.codecs.encoding.ts @@ -6,7 +6,7 @@ import {Encoder as CompactEncoder} from '../codec/structural/compact/Encoder'; import {Encoder as VerboseEncoder} from '../codec/structural/verbose/Encoder'; import {Encoder as IndexedEncoder} from '../codec/indexed/binary/Encoder'; import {Encoder as SidecarEncoder} from '../codec/sidecar/binary/Encoder'; -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {Model} from '../model'; const cborEncoder = new CborEncoder(); diff --git a/src/json-crdt/__bench__/bench.json.encoding.ts b/src/json-crdt/__bench__/bench.json.encoding.ts index 60a654dd36..d9f31decc1 100644 --- a/src/json-crdt/__bench__/bench.json.encoding.ts +++ b/src/json-crdt/__bench__/bench.json.encoding.ts @@ -2,7 +2,7 @@ import {payloads} from '../../__bench__/payloads'; import {IBenchmark, runBenchmarkAndSave} from '../../__bench__/runBenchmark'; -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; import {Model} from '../model'; const benchmark: IBenchmark = { diff --git a/src/json-crdt/__bench__/util/structural-editors.ts b/src/json-crdt/__bench__/util/structural-editors.ts index deb279a760..cb7c5e0fae 100644 --- a/src/json-crdt/__bench__/util/structural-editors.ts +++ b/src/json-crdt/__bench__/util/structural-editors.ts @@ -11,8 +11,8 @@ import {Encoder as IndexedEncoder} from '../../codec/indexed/binary/Encoder'; import {Decoder as IndexedDecoder} from '../../codec/indexed/binary/Decoder'; import {Encoder as SidecarEncoder} from '../../codec/sidecar/binary/Encoder'; import {Decoder as SidecarDecoder} from '../../codec/sidecar/binary/Decoder'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import {CborDecoder} from '../../../json-pack/cbor/CborDecoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder'; const cborEncoder = new CborEncoder(); const cborDecoder = new CborDecoder(); diff --git a/src/json-crdt/__tests__/fuzzer/generate-trace.ts b/src/json-crdt/__tests__/fuzzer/generate-trace.ts index 88307e8f54..2d07cedee8 100644 --- a/src/json-crdt/__tests__/fuzzer/generate-trace.ts +++ b/src/json-crdt/__tests__/fuzzer/generate-trace.ts @@ -4,8 +4,8 @@ import {Patch} from '../../../json-crdt-patch'; import {Model} from '../../model'; import {JsonCrdtFuzzer} from './JsonCrdtFuzzer'; -import {CborEncoder} from '../../../json-pack/cbor/CborEncoder'; -import {Writer} from '../../../util/buffers/Writer'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import * as fs from 'fs'; const sessionNum = 100; diff --git a/src/json-size/__bench__/json-size.ts b/src/json-size/__bench__/json-size.ts index 8547c0e6f1..c806dd5b77 100644 --- a/src/json-size/__bench__/json-size.ts +++ b/src/json-size/__bench__/json-size.ts @@ -3,7 +3,7 @@ // npx ts-node src/json-size/__bench__/json-size.ts import * as Benchmark from 'benchmark'; -import {utf8Size} from '../../util/strings/utf8'; +import {utf8Size} from '@jsonjoy.com/json-pack/lib/util/strings/utf8'; import {jsonSize, jsonSizeApprox} from '../json'; import {jsonSizeFast} from '../jsonSizeFast'; import {msgpackSizeFast} from '../msgpackSizeFast'; diff --git a/src/json-type/__bench__/encode.ts b/src/json-type/__bench__/encode.ts index 2ff6dca6a5..1b6c2b4945 100644 --- a/src/json-type/__bench__/encode.ts +++ b/src/json-type/__bench__/encode.ts @@ -1,11 +1,11 @@ /* tslint:disable no-console */ import {TypeSystem} from '..'; -import {CborEncoder} from '../../json-pack/cbor/CborEncoder'; -import {JsonEncoder} from '../../json-pack/json/JsonEncoder'; +import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder'; +import {JsonEncoder} from '@jsonjoy.com/json-pack/lib/json/JsonEncoder'; import {CompiledBinaryEncoder} from '../codegen/types'; -import {EncodingFormat} from '../../json-pack/constants'; -import {Writer} from '../../util/buffers/Writer'; +import {EncodingFormat} from '@jsonjoy.com/json-pack/lib/constants'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; const system = new TypeSystem(); const {t} = system; diff --git a/src/server/__bench__/ping.bench.ts b/src/server/__bench__/ping.bench.ts index 6a8fce31f8..50ea60a779 100644 --- a/src/server/__bench__/ping.bench.ts +++ b/src/server/__bench__/ping.bench.ts @@ -4,11 +4,11 @@ import {Suite} from 'benchmark'; import {RpcPersistentClient, WebSocketChannel} from '../../reactive-rpc/common'; -import {Writer} from '../../util/buffers/Writer'; +import {Writer} from '@jsonjoy.com/json-pack/lib/util/buffers/Writer'; import {BinaryRpcMessageCodec} from '../../reactive-rpc/common/codec/binary'; import {CompactRpcMessageCodec} from '../../reactive-rpc/common/codec/compact'; -import {CborJsonValueCodec} from '../../json-pack/codecs/cbor'; -import {JsonJsonValueCodec} from '../../json-pack/codecs/json'; +import {CborJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/cbor'; +import {JsonJsonValueCodec} from '@jsonjoy.com/json-pack/lib/codecs/json'; import {RpcCodec} from '../../reactive-rpc/common/codec/RpcCodec'; import {WebSocket} from 'ws';