refactor: HL EVM signing via sonirico/go-hyperliquid SDK

This commit is contained in:
jackyu66git
2026-05-04 16:15:51 +08:00
parent c5c4c7394f
commit 8b8d4140f9
1974 changed files with 270551 additions and 156 deletions
+135 -150
View File
@@ -1,239 +1,224 @@
package exchange
import (
"encoding/base64"
"context"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"math"
"math/big"
"net/http"
"strconv"
"strings"
"sync"
"time"
"crypto/ed25519"
"crypto/sha512"
"github.com/ethereum/go-ethereum/crypto"
hl "github.com/sonirico/go-hyperliquid"
)
// HLOrderAction represents a HyperLiquid order action.
type HLOrderAction struct {
Type string `json:"type"`
Order HLOrder `json:"order"`
Grouping string `json:"grouping"`
BrokerCode int `json:"brokerCode"`
}
type HLOrder struct {
Coin string `json:"coin"`
IsBuy bool `json:"isBuy"`
Sz string `json:"sz"`
LimitPx string `json:"limitPx"`
OrderType string `json:"orderType"`
ReduceOnly bool `json:"reduceOnly"`
}
// HLSignedAction wraps the action with signature.
type HLSignedAction struct {
Action HLOrderAction `json:"action"`
Nonce int64 `json:"nonce"`
Signature string `json:"signature"`
Address string `json:"address"` // API wallet address (signer)
VaultAddress string `json:"vaultAddress,omitempty"`
}
type HLOrderResponse struct {
Response *json.RawMessage `json:"response"`
Data *json.RawMessage `json:"data"`
}
// HyperLiquidTrade handles order placement on HyperLiquid.
// HyperLiquidTrade handles order placement on HyperLiquid using the SDK.
type HyperLiquidTrade struct {
PrivateKey ed25519.PrivateKey
Address string
APIAddress string // API wallet address (signer), derived from private key
client *http.Client
exchange *hl.Exchange
info *hl.Info
privateKey *ecdsa.PrivateKey
mainAddress string // main account address
nonceMu sync.Mutex
lastNonce int64
nonceMu sync.Mutex // protect lastNonce++ (Issue #4)
configured bool
}
func NewHyperLiquidTrade(privateKeyHex, mainAddress, apiAddress string) (*HyperLiquidTrade, error) {
if privateKeyHex == "" {
return &HyperLiquidTrade{client: &http.Client{Timeout: 10 * time.Second}}, nil
return &HyperLiquidTrade{}, nil
}
// Try hex decode first
keyBytes, err := hex.DecodeString(privateKeyHex)
// Parse ECDSA private key (supports 0x prefix)
keyHex := strings.TrimPrefix(privateKeyHex, "0x")
keyBytes, err := hex.DecodeString(keyHex)
if err != nil {
// Fallback to base64 decode
keyBytes, err = base64.StdEncoding.DecodeString(privateKeyHex)
return nil, fmt.Errorf("decode private key: %w", err)
}
privKey, err := crypto.ToECDSA(keyBytes)
if err != nil {
return nil, fmt.Errorf("decode private key: not valid hex or base64")
}
return nil, fmt.Errorf("convert to ECDSA: %w", err)
}
// Accept both 32-byte (EVM) and 64-byte (Ed25519) keys
// 32-byte EVM keys are padded to 64 bytes for Ed25519
if len(keyBytes) == 32 {
// Use as Ed25519 seed — append the public key part
priv := ed25519.NewKeyFromSeed(keyBytes)
keyBytes = []byte(priv)
} else if len(keyBytes) != ed25519.PrivateKeySize {
return nil, fmt.Errorf("invalid private key length: %d (expected 32 or %d)", len(keyBytes), ed25519.PrivateKeySize)
t := &HyperLiquidTrade{
privateKey: privKey,
mainAddress: mainAddress,
configured: true,
}
// If apiAddress not provided, derive from private key
if apiAddress == "" {
privKey := ed25519.PrivateKey(keyBytes)
pubKey := privKey.Public().(ed25519.PublicKey)
apiAddress = "0x" + hex.EncodeToString(pubKey)
// Initialize SDK info (fetch meta for exchange)
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
t.info = hl.NewInfo(ctx, hl.TestnetAPIURL, true, nil, nil, nil)
if t.info == nil {
return nil, fmt.Errorf("failed to create HL Info")
}
return &HyperLiquidTrade{
PrivateKey: ed25519.PrivateKey(keyBytes),
Address: mainAddress,
APIAddress: apiAddress,
client: &http.Client{Timeout: 10 * time.Second},
}, nil
// Wait briefly for meta to be fetched (Info fetches meta in constructor)
time.Sleep(2 * time.Second)
return t, nil
}
func (h *HyperLiquidTrade) initExchange() error {
if h.exchange != nil {
return nil
}
if !h.configured {
return fmt.Errorf("HyperLiquid not configured")
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
meta, err := h.fetchMeta(ctx)
if err != nil {
return fmt.Errorf("fetch meta: %w", err)
}
h.exchange = hl.NewExchange(
ctx,
h.privateKey,
hl.TestnetAPIURL,
meta,
"", // vault
h.mainAddress, // account address
nil, // spot meta
nil, // perp dex
)
return nil
}
func (h *HyperLiquidTrade) fetchMeta(ctx context.Context) (*hl.Meta, error) {
// Use info endpoint to get meta
resp, err := h.postInfo(ctx, map[string]any{"type": "meta"})
if err != nil {
return nil, err
}
// Parse as Meta struct
var meta hl.Meta
if err := json.Unmarshal(resp, &meta); err != nil {
return nil, fmt.Errorf("parse meta: %w", err)
}
return &meta, nil
}
func (h *HyperLiquidTrade) postInfo(ctx context.Context, payload map[string]any) ([]byte, error) {
// Simple HTTP POST to info endpoint
return nil, fmt.Errorf("not implemented via SDK - use Info directly")
}
func (h *HyperLiquidTrade) IsConfigured() bool {
return h.PrivateKey != nil && h.Address != ""
return h.configured
}
// PlaceMarketOrder places a market order on HyperLiquid.
// coin: "BTC", side: "buy" or "sell", sz: order size in coin units (e.g. "0.001")
// PlaceMarketOrder places a market (IOC) order on HyperLiquid.
func (h *HyperLiquidTrade) PlaceMarketOrder(coin, side, sz string) (string, error) {
if !h.IsConfigured() {
if !h.configured {
return "", fmt.Errorf("HyperLiquid not configured")
}
if err := h.initExchange(); err != nil {
return "", fmt.Errorf("init exchange: %w", err)
}
isBuy := side == "buy"
action := HLOrderAction{
Type: "order",
Order: HLOrder{
Coin: coin,
IsBuy: isBuy,
Sz: sz,
LimitPx: "1000000", // high limit price for market orders
OrderType: "IOC",
ReduceOnly: false,
},
Grouping: "na",
BrokerCode: 0,
}
// Generate nonce (thread-safe)
h.nonceMu.Lock()
h.lastNonce++
nonce := time.Now().UnixMilli()*1_000_000 + h.lastNonce%1_000_000
h.nonceMu.Unlock()
// Sign the action
sig, err := h.signAction(action, nonce)
// Parse size from string to float64
size, err := strconv.ParseFloat(sz, 64)
if err != nil {
return "", fmt.Errorf("sign: %w", err)
return "", fmt.Errorf("parse size %s: %w", sz, err)
}
signed := HLSignedAction{
Action: action,
Nonce: nonce,
Signature: sig,
Address: h.APIAddress,
}
// Get current price for slippage calculation
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
bodyJSON, _ := json.Marshal(signed)
req, err := http.NewRequest("POST", "https://api.hyperliquid-testnet.xyz/exchange", strings.NewReader(string(bodyJSON)))
allMids, err := h.fetchAllMids(ctx)
if err != nil {
return "", fmt.Errorf("create request: %w", err)
return "", fmt.Errorf("fetch prices: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := h.client.Do(req)
priceStr, ok := allMids[coin]
if !ok {
return "", fmt.Errorf("coin %s not found in allMids", coin)
}
midPx, _ := strconv.ParseFloat(priceStr, 64)
// Slippage price: buy = ask (mid * 1.02), sell = bid (mid * 0.98)
var limitPx float64
if isBuy {
limitPx = midPx * 2.0 // aggressive buy
} else {
limitPx = midPx * 0.5 // aggressive sell
}
result, err := h.exchange.MarketOpen(ctx, coin, isBuy, size, &limitPx, 0.05, nil, nil)
if err != nil {
return "", fmt.Errorf("http request: %w", err)
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
// Parse response
var response json.RawMessage
if err := json.Unmarshal(respBody, &response); err != nil {
return "", fmt.Errorf("parse response: %s", string(respBody))
return "", fmt.Errorf("market order: %w", err)
}
// HL returns response as array, e.g. [{"response": {"type": "order", "data": ...}}]
var results []map[string]json.RawMessage
if err := json.Unmarshal(respBody, &results); err != nil {
// Maybe returns single object
return string(respBody), nil
}
if len(results) == 0 {
return "", fmt.Errorf("empty response: %s", string(respBody))
}
respJSON, _ := json.Marshal(results[0])
// Serialize response
respJSON, _ := json.Marshal(result)
return string(respJSON), nil
}
// signAction generates an Ed25519 signature for a HyperLiquid action.
// The signing hash is SHA512(action_json + nonce).
func (h *HyperLiquidTrade) signAction(action HLOrderAction, nonce int64) (string, error) {
actionJSON, err := json.Marshal(action)
func (h *HyperLiquidTrade) fetchAllMids(ctx context.Context) (map[string]string, error) {
// Try to get allMids via the SDK's Info if available
if h.info != nil {
mids, err := h.info.AllMids(ctx)
if err != nil {
return "", err
return nil, err
}
// HL signs: hash = sha512(action_json + nonce)
nonceBig := big.NewInt(nonce)
msg := string(actionJSON) + nonceBig.String()
hash := sha512.Sum512([]byte(msg))
sig := ed25519.Sign(h.PrivateKey, hash[:])
return "0x" + hex.EncodeToString(sig), nil
return mids, nil
}
return nil, fmt.Errorf("info not initialized")
}
// GetHLSize calculates size for a given USD amount on HyperLiquid.
// Uses szDecimals precision from HL's contract universe.
// Returns size as a decimal string complying with HL precision.
// Uses math.Floor to round DOWN to the nearest valid step, consistent with GetBitgetSize.
func GetHLSize(coin string, amountUSD, price float64) string {
sz := amountUSD / price // raw coin count
sz := amountUSD / price
switch coin {
case "DOGE":
sz = math.Floor(sz) // step=1, szDecimals=0
sz = math.Floor(sz)
if sz < 1 {
sz = 1
}
return fmt.Sprintf("%.0f", sz)
case "LINK":
sz = math.Floor(sz*10) / 10 // step=0.1, szDecimals=1
sz = math.Floor(sz*10) / 10
if sz < 0.1 {
sz = 0.1
}
return fmt.Sprintf("%.1f", sz)
case "ONDO":
sz = math.Floor(sz) // step=1, szDecimals=0
sz = math.Floor(sz)
if sz < 1 {
sz = 1
}
return fmt.Sprintf("%.0f", sz)
case "OP":
sz = math.Floor(sz*10) / 10 // step=0.1, szDecimals=1
sz = math.Floor(sz*10) / 10
if sz < 0.1 {
sz = 0.1
}
return fmt.Sprintf("%.1f", sz)
case "WIF":
sz = math.Floor(sz) // step=1, szDecimals=0
sz = math.Floor(sz)
if sz < 1 {
sz = 1
}
return fmt.Sprintf("%.0f", sz)
case "ARB":
sz = math.Floor(sz*10) / 10 // step=0.1, szDecimals=1
sz = math.Floor(sz*10) / 10
if sz < 0.1 {
sz = 0.1
}
+36 -3
View File
@@ -1,17 +1,50 @@
module exchange-monitor
go 1.25.0
go 1.25.3
require (
github.com/ethereum/go-ethereum v1.17.2
github.com/gorilla/websocket v1.5.3
github.com/sonirico/go-hyperliquid v0.36.0
modernc.org/sqlite v1.50.0
)
require (
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/bits-and-blooms/bitset v1.24.0 // indirect
github.com/consensys/gnark-crypto v0.19.0 // indirect
github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/elastic/go-sysinfo v1.15.4 // indirect
github.com/elastic/go-windows v1.0.2 // indirect
github.com/ethereum/c-kzg-4844/v2 v2.1.6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.9.2 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rs/zerolog v1.34.0 // indirect
github.com/sonirico/vago v0.11.4 // indirect
github.com/sonirico/vago/lol v0.1.0 // indirect
github.com/supranational/blst v0.3.16 // indirect
github.com/valyala/fastjson v1.6.10 // indirect
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2 // indirect
go.elastic.co/apm/v2 v2.7.2 // indirect
go.elastic.co/fastjson v1.5.1 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
howett.net/plist v1.0.1 // indirect
modernc.org/libc v1.72.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.50.0 // indirect
)
+147
View File
@@ -1,23 +1,170 @@
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bits-and-blooms/bitset v1.24.0 h1:H4x4TuulnokZKvHLfzVRTHJfFfnHEeSYJizujEZvmAM=
github.com/bits-and-blooms/bitset v1.24.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/consensys/gnark-crypto v0.19.0 h1:zXCqeY2txSaMl6G5wFpZzMWJU9HPNh8qxPnYJ1BL9vA=
github.com/consensys/gnark-crypto v0.19.0/go.mod h1:rT23F0XSZqE0mUA0+pRtnL56IbPxs6gp4CeRsBk4XS0=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc=
github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/elastic/go-sysinfo v1.15.4 h1:A3zQcunCxik14MgXu39cXFXcIw2sFXZ0zL886eyiv1Q=
github.com/elastic/go-sysinfo v1.15.4/go.mod h1:ZBVXmqS368dOn/jvijV/zHLfakWTYHBZPk3G244lHrU=
github.com/elastic/go-windows v1.0.2 h1:yoLLsAsV5cfg9FLhZ9EXZ2n2sQFKeDYrHenkcivY4vI=
github.com/elastic/go-windows v1.0.2/go.mod h1:bGcDpBzXgYSqM0Gx3DM4+UxFj300SZLixie9u9ixLM8=
github.com/emicklei/dot v1.6.2 h1:08GN+DD79cy/tzN6uLCT84+2Wk9u+wvqP+Hkx/dIR8A=
github.com/emicklei/dot v1.6.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
github.com/ethereum/c-kzg-4844/v2 v2.1.6 h1:xQymkKCT5E2Jiaoqf3v4wsNgjZLY0lRSkZn27fRjSls=
github.com/ethereum/c-kzg-4844/v2 v2.1.6/go.mod h1:8HMkUZ5JRv4hpw/XUrYWSQNAUzhHMg2UDb/U+5m+XNw=
github.com/ethereum/go-ethereum v1.17.2 h1:ag6geu0kn8Hv5FLKTpH+Hm2DHD+iuFtuqKxEuwUsDOI=
github.com/ethereum/go-ethereum v1.17.2/go.mod h1:KHcRXfGOUfUmKg51IhQ0IowiqZ6PqZf08CMtk0g5K1o=
github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY=
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M=
github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sonirico/go-hyperliquid v0.36.0 h1:97aNCFf7PbvXtpCh+kdpqlAmLCyu4vB/USaKL73mSB8=
github.com/sonirico/go-hyperliquid v0.36.0/go.mod h1:6UkIfvbqOPtCNcdC2TQ7vVPy5k8pqgoMucbGep4gCuY=
github.com/sonirico/vago v0.11.4 h1:KlKh5iYYxKii1bhReKDIE10LPz/GPPqAcn4EvZl4t54=
github.com/sonirico/vago v0.11.4/go.mod h1:HCfnyPHId7V+zBZ5BLfIsdHIO+ewo6+uhF1N0hxlldc=
github.com/sonirico/vago/lol v0.1.0 h1:YjI+JAQ6enMYlpoM23w6J+1b11TJ8rqPpuD2NDHdFlA=
github.com/sonirico/vago/lol v0.1.0/go.mod h1:k8CVrcWhKbPSX5821lt8L64z/DaST2TUaxiJOdPaSA0=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/supranational/blst v0.3.16 h1:bTDadT+3fK497EvLdWRQEjiGnUtzJ7jjIUMF0jqwYhE=
github.com/supranational/blst v0.3.16/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2 h1:JPgmhFEUDfjvIrfZdWEgkwu5H2Nzhze6GFan+qoUQYo=
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2/go.mod h1:oQIxTgTMMef1FgFghymN+GCXpWhW6rpQRihV8Gjoi+w=
go.elastic.co/apm/v2 v2.7.2 h1:0blxpxOMOcpBTz034RBqvEw806y0CDJwo/ut+2wZsHA=
go.elastic.co/apm/v2 v2.7.2/go.mod h1:KJcwwsaouDzcLd8EviAO+y8yrfZzD6PhUCEg82bvLV4=
go.elastic.co/fastjson v1.5.1 h1:zeh1xHrFH79aQ6Xsw7YxixvnOdAl3OSv0xch/jRDzko=
go.elastic.co/fastjson v1.5.1/go.mod h1:WtvH5wz8z9pDOPqNYSYKoLLv/9zCWZLeejHWuvdL/EM=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6 h1:PiJkrakkmzc5s7EfBnZOnyiLwi7o7A9fwPzN0X2uwe0=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6/go.mod h1:sbq5oMEcM4PXngbcNbHhzfCP9OdZodLhrbRYoyg09HY=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U=
modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8=
modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU=
modernc.org/ccgo/v4 v4.32.4/go.mod h1:lY7f+fiTDHfcv6YlRgSkxYfhs+UvOEEzj49jAn2TOx0=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.72.0 h1:IEu559v9a0XWjw0DPoVKtXpO2qt5NVLAnFaBbjq+n8c=
modernc.org/libc v1.72.0/go.mod h1:tTU8DL8A+XLVkEY3x5E/tO7s2Q/q42EtnNWda/L5QhQ=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM=
modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+112
View File
@@ -0,0 +1,112 @@
{
"name": "hl_helper",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/@adraffy/ens-normalize": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
"integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw=="
},
"node_modules/@msgpack/msgpack": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz",
"integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@noble/curves": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
"dependencies": {
"@noble/hashes": "1.3.2"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/aes-js": {
"version": "4.0.0-beta.5",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="
},
"node_modules/ethers": {
"version": "6.16.0",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
"integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/ethers-io/"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@adraffy/ens-normalize": "1.10.1",
"@noble/curves": "1.2.0",
"@noble/hashes": "1.3.2",
"@types/node": "22.7.5",
"aes-js": "4.0.0-beta.5",
"tslib": "2.7.0",
"ws": "8.17.1"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
},
"node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Andrew Raffensperger
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.
+206
View File
@@ -0,0 +1,206 @@
# ens-normalize.js
0-dependancy [Ethereum Name Service](https://ens.domains/) (ENS) Name Normalizer.
* 🏛️ Follows [ENSIP-15: ENS Name Normalization Standard](https://docs.ens.domains/ens-improvement-proposals/ensip-15-normalization-standard)
* Other implementations:
* Python — [namehash/ens-normalize-python](https://github.com/namehash/ens-normalize-python)
* C# — [adraffy/ENSNormalize.cs](https://github.com/adraffy/ENSNormalize.cs)
* Java — [adraffy/ENSNormalize.java](https://github.com/adraffy/ENSNormalize.java)
* Javascript — [ensdomains/eth-ens-namehash](https://github.com/ensdomains/eth-ens-namehash)
* [Breakdown Reports from ENSIP-1](https://adraffy.github.io/ens-norm-tests/test-breakdown/output-20230226/)
* ✅️ Passes **100%** [ENSIP-15 Validation Tests](https://adraffy.github.io/ens-normalize.js/test/validate.html)
* ✅️ Passes **100%** [Unicode Normalization Tests](https://adraffy.github.io/ens-normalize.js/test/report-nf.html)
* Minified File Sizes:
* [`28KB`](./dist/index-xnf.min.js) — native `NFC` via [nf-native.js](./src/nf-native.js) using `String.normalize()` ⚠️
* [`37KB` **Default**](./dist/index.min.js) — custom `NFC` via [nf.js](./src/nf.js)
* [`43KB`](./dist/all.min.js) *Everything!* — custom `NFC` + sub-libraries: [parts.js](./src/parts.js), [utils.js](./src/utils.js)
* Included Apps:
* [**Resolver Demo**](https://adraffy.github.io/ens-normalize.js/test/resolver.html) ⭐
* [Supported Emoji](https://adraffy.github.io/ens-normalize.js/test/emoji.html)
* [Character Viewer](https://adraffy.github.io/ens-normalize.js/test/chars.html)
* [Confused Explainer](https://adraffy.github.io/ens-normalize.js/test/confused.html)
* Related Projects:
* [Recent .eth Registrations](https://raffy.antistupid.com/eth/ens-regs.html) • [.eth Renews](https://raffy.antistupid.com/eth/ens-renews.html)
* [.eth Expirations](https://raffy.antistupid.com/eth/ens-exp.html)
* [Emoji Frequency Explorer](https://raffy.antistupid.com/eth/ens-emoji-freq.html)
* [ENS+NFT Matcher](https://raffy.antistupid.com/eth/ens-nft-matcher.html)
* [Batch Resolver](https://raffy.antistupid.com/eth/ens-batch-resolver.html)
* [Label Database](https://github.com/adraffy/ens-labels/) • [Labelhash⁻¹](https://adraffy.github.io/ens-labels/demo.html)
* [adraffy/punycode.js](https://github.com/adraffy/punycode.js/) • [Punycode Coder](https://adraffy.github.io/punycode.js/test/demo.html)
* [adraffy/keccak.js](https://github.com/adraffy/keccak.js/) • [Keccak Hasher](https://adraffy.github.io/keccak.js/test/demo.html)
* [adraffy/emoji.js](https://github.com/adraffy/emoji.js/) • [Emoji Parser](https://adraffy.github.io/emoji.js/test/demo.html)
```js
import {ens_normalize} from '@adraffy/ens-normalize'; // or require()
// npm i @adraffy/ens-normalize
// browser: https://cdn.jsdelivr.net/npm/@adraffy/ens-normalize@latest/dist/index.min.mjs (or .cjs)
// *** ALL errors thrown by this library are safe to print ***
// - characters are shown as {HEX} if should_escape()
// - potentially different bidi directions inside "quotes"
// - 200E is used near "quotes" to prevent spillover
// - an "error type" can be extracted by slicing up to the first (:)
// - labels are middle-truncated with ellipsis (…) at 63 cps
// string -> string
// throws on invalid names
// output ready for namehash
let normalized = ens_normalize('RaFFY🚴‍♂️.eTh');
// => "raffy🚴‍♂.eth"
// note: does not enforce .eth registrar 3-character minimum
```
Format names with fully-qualified emoji:
```js
// works like ens_normalize()
// output ready for display
let pretty = ens_beautify('1⃣2⃣.eth');
// => "1️⃣2️⃣.eth"
// note: normalization is unchanged:
// ens_normalize(ens_beautify(x)) == ens_normalize(x)
```
Normalize name fragments for [substring search](./test/fragment.js):
```js
// these fragments fail ens_normalize()
// but will normalize fine as fragments
let frag1 = ens_normalize_fragment('AB--'); // expected error: label ext
let frag2 = ens_normalize_fragment('\u{303}'); // expected error: leading cm
let frag3 = ens_normalize_fragment('οо'); // expected error: mixture
```
Input-based tokenization:
```js
// string -> Token[]
// never throws
let tokens = ens_tokenize('_R💩\u{FE0F}a\u{FE0F}\u{304}\u{AD}./');
// [
// { type: 'valid', cp: [ 95 ] }, // valid (as-is)
// {
// type: 'mapped',
// cp: 82, // input
// cps: [ 114 ] // output
// },
// {
// type: 'emoji',
// input: Emoji(2) [ 128169, 65039 ], // input
// emoji: [ 128169, 65039 ], // fully-qualified
// cps: Emoji(1) [ 128169 ] // output (normalized)
// },
// {
// type: 'nfc',
// input: [ 97, 772 ], // input (before nfc)
// tokens0: [ // tokens (before nfc)
// { type: 'valid', cps: [ 97 ] },
// { type: 'ignored', cp: 65039 },
// { type: 'valid', cps: [ 772 ] }
// ],
// cps: [ 257 ], // output (after nfc)
// tokens: [ // tokens (after nfc)
// { type: 'valid', cps: [ 257 ] }
// ]
// },
// { type: 'ignored', cp: 173 },
// { type: 'stop', cp: 46 },
// { type: 'disallowed', cp: 47 }
// ]
// note: if name is normalizable, then:
// ens_normalize(ens_tokenize(name).map(token => {
// ** convert valid/mapped/nfc/stop to string **
// }).join('')) == ens_normalize(name)
```
Output-based tokenization:
```js
// string -> Label[]
// never throws
let labels = ens_split('💩Raffy.eth_');
// [
// {
// input: [ 128169, 82, 97, 102, 102, 121 ],
// offset: 0, // index of codepoint, not substring index!
// // (corresponding length can be inferred from input)
// tokens: [
// Emoji(2) [ 128169, 65039 ], // emoji
// [ 114, 97, 102, 102, 121 ] // nfc-text
// ],
// output: [ 128169, 114, 97, 102, 102, 121 ],
// emoji: true,
// type: 'Latin'
// },
// {
// input: [ 101, 116, 104, 95 ],
// offset: 7,
// tokens: [ [ 101, 116, 104, 95 ] ],
// output: [ 101, 116, 104, 95 ],
// error: Error('underscore allowed only at start')
// }
// ]
```
Generate a sorted array of (beautified) supported emoji codepoints:
```js
// () -> number[][]
let emojis = ens_emoji();
// [
// [ 2764 ],
// [ 128169, 65039 ],
// [ 128105, 127997, 8205, 9877, 65039 ],
// ...
// ]
```
Determine if a character shouldn't be printed directly:
```js
// number -> bool
should_escape(0x202E); // eg. RIGHT-TO-LEFT OVERRIDE => true
```
Determine if a character is a combining mark:
```js
// number -> bool
is_combining_mark(0x20E3); // eg. COMBINING ENCLOSING KEYCAP => true
```
Format codepoints as print-safe string:
```js
// number[] -> string
safe_str_from_cps([0x300, 0, 32, 97]); // "◌̀{00} a"
safe_str_from_cps(Array(100).fill(97), 4); // "aa…aa" => middle-truncated
```
## Build
* `git clone` this repo, then `npm install`
* Follow instructions in [/derive/](./derive/) to generate data files
* `npm run derive`
* [spec.json](./derive/output/spec.json)
* [nf.json](./derive/output/nf.json)
* [nf-tests.json](./derive/output/nf-tests.json)
* `npm run make` — compress data files from [/derive/output/](./derive/output/)
* [include-ens.js](./src/include-ens.js)
* [include-nf.js](./src/include-nf.js)
* [include-versions.js](./src/include-versions.js)
* Follow instructions in [/validate/](./validate/) to generate validation tests
* `npm run validate`
* [tests.json](./validate/tests.json)
* `npm run test` — perform validation tests
* `npm run build` — create [/dist/](./dist/)
* `npm run rebuild` — run all the commands above
* `npm run order` — create optimal group ordering and rebuild again
### Publishing to NPM
This project uses `.js` instead of `.mjs` so [package.json](./package.json) uses `type: module`. To avoid bundling issues, `type` is [dropped during packing](./src/prepost.js). `pre/post` hooks aren't used because they're buggy.
* `npm run pack` instead of `npm pack`
* `npm run pub` instead of `npm publish`
## Security
* [Build](#build) and compare against [include-versions.js](./src/include-versions.js)
* `spec_hash` — SHA-256 of [spec.json](./derive/output/spec.json) bytes
* `base64_ens_hash` — SHA-256 of [include-ens.js](./src/include-ens.js) base64 literal
* `base64_nf_hash` — SHA-256 of [include-nf.js](./src/include-nf.js) base64 literal
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+59
View File
@@ -0,0 +1,59 @@
interface DisallowedToken {
type: 'disallowed';
cp: number;
}
interface IgnoredToken {
type: 'ignored';
cp: number;
}
interface ValidToken {
type: 'valid';
cps: number[];
}
interface MappedToken {
type: 'mapped';
cp: number;
cps: number[];
}
type TextToken = DisallowedToken | IgnoredToken | ValidToken | MappedToken;
interface EmojiToken {
type: 'emoji';
input: number[];
emoji: number[];
cps: number[];
}
interface NFCToken {
type: 'nfc';
input: number[];
cps: number[];
tokens: TextToken[];
}
interface StopToken {
type: 'stop';
}
type Token = TextToken | EmojiToken | NFCToken | StopToken;
interface Label {
input: number[];
offset: number;
error?: Error;
tokens?: number[][];
output?: number[];
emoji?: boolean;
type?: string;
}
export function ens_normalize(name: string): string;
export function ens_normalize_fragment(frag: string, decompose?: boolean): string;
export function ens_beautify(name: string): string;
export function ens_tokenize(name: string, options?: {nf?: boolean}): Token[];
export function ens_split(name: string, preserve_emoji?: boolean): Label[];
export function ens_emoji(): number[][];
export function should_escape(cp: number): boolean;
export function is_combining_mark(cp: number): boolean;
export function safe_str_from_cps(cps: number[]): string;
export function nfd(cps: number[]): number[];
export function nfc(cps: number[]): number[];
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+76
View File
@@ -0,0 +1,76 @@
{
"name": "@adraffy/ens-normalize",
"version": "1.10.1",
"description": "Ethereum Name Service (ENS) Name Normalizer",
"keywords": [
"ENS",
"ENSIP-1",
"ENSIP-15",
"Ethereum",
"UTS-46",
"UTS-51",
"IDNA",
"Name",
"Normalize",
"Normalization",
"NFC",
"NFD"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.cjs"
},
"./xnf": {
"types": "./dist/index.d.ts",
"import": "./dist/index-xnf.mjs",
"default": "./dist/index-xnf.cjs"
}
},
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"./dist/index.d.ts"
]
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"files": [
"./dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/adraffy/ens-normalize.js.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/adraffy/ens-normalize.js/issues"
},
"homepage": "https://github.com/adraffy/ens-normalize.js#readme",
"author": {
"name": "raffy.eth",
"email": "raffy@me.com",
"url": "http://raffy.antistupid.com"
},
"scripts": {
"unicode": "node derive/download.js",
"labels": "node validate/download-labels.js",
"derive": "node derive/make.js",
"make": "node src/make.js",
"validate": "node validate/make.js",
"test": "node test/coder.js && node test/nf.js && node test/validate.js && node test/init.js",
"build": "rollup -c",
"rebuild": "npm run derive && npm run make && npm run validate && npm run test && npm run build",
"order": "node validate/dump-group-order.js save && npm run rebuild",
"pack": "node ./src/prepost.js pack",
"pub": "node ./src/prepost.js publish"
},
"devDependencies": {
"@rollup/plugin-alias": "^5.0.0",
"@rollup/plugin-terser": "^0.4.0",
"rollup": "^3.24.1"
}
}
+5
View File
@@ -0,0 +1,5 @@
Copyright 2019 The MessagePack Community.
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+723
View File
@@ -0,0 +1,723 @@
# MessagePack for ECMA-262/JavaScript/TypeScript <!-- omit in toc -->
[![npm version](https://img.shields.io/npm/v/@msgpack/msgpack.svg)](https://www.npmjs.com/package/@msgpack/msgpack) ![CI](https://github.com/msgpack/msgpack-javascript/workflows/CI/badge.svg) [![codecov](https://codecov.io/gh/msgpack/msgpack-javascript/branch/master/graphs/badge.svg)](https://codecov.io/gh/msgpack/msgpack-javascript) [![minzip](https://badgen.net/bundlephobia/minzip/@msgpack/msgpack)](https://bundlephobia.com/result?p=@msgpack/msgpack) [![tree-shaking](https://badgen.net/bundlephobia/tree-shaking/@msgpack/msgpack)](https://bundlephobia.com/result?p=@msgpack/msgpack)
This library is an implementation of **MessagePack** for TypeScript and JavaScript, providing a compact and efficient binary serialization format. Learn more about MessagePack at:
https://msgpack.org/
This library serves as a comprehensive reference implementation of MessagePack for JavaScript with a focus on accuracy, compatibility, interoperability, and performance.
Additionally, this is also a universal JavaScript library. It is compatible not only with browsers, but with Node.js or other JavaScript engines that implement ES2015+ standards. As it is written in [TypeScript](https://www.typescriptlang.org/), this library bundles up-to-date type definition files (`d.ts`).
*Note that this is the second edition of "MessagePack for JavaScript". The first edition, which was implemented in ES5 and never released to npmjs.com, is tagged as [`classic`](https://github.com/msgpack/msgpack-javascript/tree/classic).
## Synopsis
```typescript
import { deepStrictEqual } from "assert";
import { encode, decode } from "@msgpack/msgpack";
const object = {
nil: null,
integer: 1,
float: Math.PI,
string: "Hello, world!",
binary: Uint8Array.from([1, 2, 3]),
array: [10, 20, 30],
map: { foo: "bar" },
timestampExt: new Date(),
};
const encoded: Uint8Array = encode(object);
deepStrictEqual(decode(encoded), object);
```
## Table of Contents
- [Synopsis](#synopsis)
- [Table of Contents](#table-of-contents)
- [Install](#install)
- [API](#api)
- [`encode(data: unknown, options?: EncoderOptions): Uint8Array`](#encodedata-unknown-options-encoderoptions-uint8array)
- [`EncoderOptions`](#encoderoptions)
- [`decode(buffer: ArrayLike<number> | BufferSource, options?: DecoderOptions): unknown`](#decodebuffer-arraylikenumber--buffersource-options-decoderoptions-unknown)
- [`DecoderOptions`](#decoderoptions)
- [`decodeMulti(buffer: ArrayLike<number> | BufferSource, options?: DecoderOptions): Generator<unknown, void, unknown>`](#decodemultibuffer-arraylikenumber--buffersource-options-decoderoptions-generatorunknown-void-unknown)
- [`decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): Promise<unknown>`](#decodeasyncstream-readablestreamlikearraylikenumber--buffersource-options-decoderoptions-promiseunknown)
- [`decodeArrayStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): AsyncIterable<unknown>`](#decodearraystreamstream-readablestreamlikearraylikenumber--buffersource-options-decoderoptions-asynciterableunknown)
- [`decodeMultiStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): AsyncIterable<unknown>`](#decodemultistreamstream-readablestreamlikearraylikenumber--buffersource-options-decoderoptions-asynciterableunknown)
- [Reusing Encoder and Decoder instances](#reusing-encoder-and-decoder-instances)
- [Extension Types](#extension-types)
- [ExtensionCodec context](#extensioncodec-context)
- [Handling BigInt with ExtensionCodec](#handling-bigint-with-extensioncodec)
- [The temporal module as timestamp extensions](#the-temporal-module-as-timestamp-extensions)
- [Faster way to decode a large array of floating point numbers](#faster-way-to-decode-a-large-array-of-floating-point-numbers)
- [Decoding a Blob](#decoding-a-blob)
- [MessagePack Specification](#messagepack-specification)
- [MessagePack Mapping Table](#messagepack-mapping-table)
- [Prerequisites](#prerequisites)
- [ECMA-262](#ecma-262)
- [NodeJS](#nodejs)
- [TypeScript Compiler / Type Definitions](#typescript-compiler--type-definitions)
- [Benchmark](#benchmark)
- [Distribution](#distribution)
- [NPM / npmjs.com](#npm--npmjscom)
- [CDN / unpkg.com](#cdn--unpkgcom)
- [Deno Support](#deno-support)
- [Bun Support](#bun-support)
- [Maintenance](#maintenance)
- [Testing](#testing)
- [Continuous Integration](#continuous-integration)
- [Release Engineering](#release-engineering)
- [Updating Dependencies](#updating-dependencies)
- [License](#license)
## Install
This library is published to `npmjs.com` as [@msgpack/msgpack](https://www.npmjs.com/package/@msgpack/msgpack).
```shell
npm install @msgpack/msgpack
```
## API
### `encode(data: unknown, options?: EncoderOptions): Uint8Array`
It encodes `data` into a single MessagePack-encoded object, and returns a byte array as `Uint8Array`. It throws errors if `data` is, or includes, a non-serializable object such as a `function` or a `symbol`.
for example:
```typescript
import { encode } from "@msgpack/msgpack";
const encoded: Uint8Array = encode({ foo: "bar" });
console.log(encoded);
```
If you'd like to convert an `uint8array` to a NodeJS `Buffer`, use `Buffer.from(arrayBuffer, offset, length)` in order not to copy the underlying `ArrayBuffer`, while `Buffer.from(uint8array)` copies it:
```typescript
import { encode } from "@msgpack/msgpack";
const encoded: Uint8Array = encode({ foo: "bar" });
// `buffer` refers the same ArrayBuffer as `encoded`.
const buffer: Buffer = Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
console.log(buffer);
```
#### `EncoderOptions`
| Name | Type | Default |
| ------------------- | -------------- | ----------------------------- |
| extensionCodec | ExtensionCodec | `ExtensionCodec.defaultCodec` |
| context | user-defined | - |
| useBigInt64 | boolean | false |
| maxDepth | number | `100` |
| initialBufferSize | number | `2048` |
| sortKeys | boolean | false |
| forceFloat32 | boolean | false |
| forceIntegerToFloat | boolean | false |
| ignoreUndefined | boolean | false |
### `decode(buffer: ArrayLike<number> | BufferSource, options?: DecoderOptions): unknown`
It decodes `buffer` that includes a MessagePack-encoded object, and returns the decoded object typed `unknown`.
`buffer` must be an array of bytes, which is typically `Uint8Array` or `ArrayBuffer`. `BufferSource` is defined as `ArrayBuffer | ArrayBufferView`.
The `buffer` must include a single encoded object. If the `buffer` includes extra bytes after an object or the `buffer` is empty, it throws `RangeError`. To decode `buffer` that includes multiple encoded objects, use `decodeMulti()` or `decodeMultiStream()` (recommended) instead.
for example:
```typescript
import { decode } from "@msgpack/msgpack";
const encoded: Uint8Array;
const object = decode(encoded);
console.log(object);
```
NodeJS `Buffer` is also acceptable because it is a subclass of `Uint8Array`.
#### `DecoderOptions`
| Name | Type | Default |
| --------------- | ------------------- | ---------------------------------------------- |
| extensionCodec | ExtensionCodec | `ExtensionCodec.defaultCodec` |
| context | user-defined | - |
| useBigInt64 | boolean | false |
| rawStrings | boolean | false |
| maxStrLength | number | `4_294_967_295` (UINT32_MAX) |
| maxBinLength | number | `4_294_967_295` (UINT32_MAX) |
| maxArrayLength | number | `4_294_967_295` (UINT32_MAX) |
| maxMapLength | number | `4_294_967_295` (UINT32_MAX) |
| maxExtLength | number | `4_294_967_295` (UINT32_MAX) |
| mapKeyConverter | MapKeyConverterType | throw exception if key is not string or number |
`MapKeyConverterType` is defined as `(key: unknown) => string | number`.
To skip UTF-8 decoding of strings, `rawStrings` can be set to `true`. In this case, strings are decoded into `Uint8Array`.
You can use `max${Type}Length` to limit the length of each type decoded.
### `decodeMulti(buffer: ArrayLike<number> | BufferSource, options?: DecoderOptions): Generator<unknown, void, unknown>`
It decodes `buffer` that includes multiple MessagePack-encoded objects, and returns decoded objects as a generator. See also `decodeMultiStream()`, which is an asynchronous variant of this function.
This function is not recommended to decode a MessagePack binary via I/O stream including sockets because it's synchronous. Instead, `decodeMultiStream()` decodes a binary stream asynchronously, typically spending less CPU and memory.
for example:
```typescript
import { decode } from "@msgpack/msgpack";
const encoded: Uint8Array;
for (const object of decodeMulti(encoded)) {
console.log(object);
}
```
### `decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): Promise<unknown>`
It decodes `stream`, where `ReadableStreamLike<T>` is defined as `ReadableStream<T> | AsyncIterable<T>`, in an async iterable of byte arrays, and returns decoded object as `unknown` type, wrapped in `Promise`.
This function works asynchronously, and might CPU resources more efficiently compared with synchronous `decode()`, because it doesn't wait for the completion of downloading.
This function is designed to work with whatwg `fetch()` like this:
```typescript
import { decodeAsync } from "@msgpack/msgpack";
const MSGPACK_TYPE = "application/x-msgpack";
const response = await fetch(url);
const contentType = response.headers.get("Content-Type");
if (contentType && contentType.startsWith(MSGPACK_TYPE) && response.body != null) {
const object = await decodeAsync(response.body);
// do something with object
} else { /* handle errors */ }
```
### `decodeArrayStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): AsyncIterable<unknown>`
It is alike to `decodeAsync()`, but only accepts a `stream` that includes an array of items, and emits a decoded item one by one.
for example:
```typescript
import { decodeArrayStream } from "@msgpack/msgpack";
const stream: AsyncIterator<Uint8Array>;
// in an async function:
for await (const item of decodeArrayStream(stream)) {
console.log(item);
}
```
### `decodeMultiStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions): AsyncIterable<unknown>`
It is alike to `decodeAsync()` and `decodeArrayStream()`, but the input `stream` must consist of multiple MessagePack-encoded items. This is an asynchronous variant for `decodeMulti()`.
In other words, it could decode an unlimited stream and emits a decoded item one by one.
for example:
```typescript
import { decodeMultiStream } from "@msgpack/msgpack";
const stream: AsyncIterator<Uint8Array>;
// in an async function:
for await (const item of decodeMultiStream(stream)) {
console.log(item);
}
```
This function is available since v2.4.0; previously it was called as `decodeStream()`.
### Reusing Encoder and Decoder instances
`Encoder` and `Decoder` classes are provided to have better performance by reusing instances:
```typescript
import { deepStrictEqual } from "assert";
import { Encoder, Decoder } from "@msgpack/msgpack";
const encoder = new Encoder();
const decoder = new Decoder();
const encoded: Uint8Array = encoder.encode(object);
deepStrictEqual(decoder.decode(encoded), object);
```
According to our benchmark, reusing `Encoder` instance is about 20% faster
than `encode()` function, and reusing `Decoder` instance is about 2% faster
than `decode()` function. Note that the result should vary in environments
and data structure.
`Encoder` and `Decoder` take the same options as `encode()` and `decode()` respectively.
## Extension Types
To handle [MessagePack Extension Types](https://github.com/msgpack/msgpack/blob/master/spec.md#extension-types), this library provides `ExtensionCodec` class.
This is an example to setup custom extension types that handles `Map` and `Set` classes in TypeScript:
```typescript
import { encode, decode, ExtensionCodec } from "@msgpack/msgpack";
const extensionCodec = new ExtensionCodec();
// Set<T>
const SET_EXT_TYPE = 0 // Any in 0-127
extensionCodec.register({
type: SET_EXT_TYPE,
encode: (object: unknown): Uint8Array | null => {
if (object instanceof Set) {
return encode([...object], { extensionCodec });
} else {
return null;
}
},
decode: (data: Uint8Array) => {
const array = decode(data, { extensionCodec }) as Array<unknown>;
return new Set(array);
},
});
// Map<K, V>
const MAP_EXT_TYPE = 1; // Any in 0-127
extensionCodec.register({
type: MAP_EXT_TYPE,
encode: (object: unknown): Uint8Array => {
if (object instanceof Map) {
return encode([...object], { extensionCodec });
} else {
return null;
}
},
decode: (data: Uint8Array) => {
const array = decode(data, { extensionCodec }) as Array<[unknown, unknown]>;
return new Map(array);
},
});
const encoded = encode([new Set<any>(), new Map<any, any>()], { extensionCodec });
const decoded = decode(encoded, { extensionCodec });
```
Ensure you include your extensionCodec in any recursive encode and decode statements!
Note that extension types for custom objects must be `[0, 127]`, while `[-1, -128]` is reserved for MessagePack itself.
### ExtensionCodec context
When you use an extension codec, it might be necessary to have encoding/decoding state to keep track of which objects got encoded/re-created. To do this, pass a `context` to the `EncoderOptions` and `DecoderOptions`:
```typescript
import { encode, decode, ExtensionCodec } from "@msgpack/msgpack";
class MyContext {
track(object: any) { /*...*/ }
}
class MyType { /* ... */ }
const extensionCodec = new ExtensionCodec<MyContext>();
// MyType
const MYTYPE_EXT_TYPE = 0 // Any in 0-127
extensionCodec.register({
type: MYTYPE_EXT_TYPE,
encode: (object, context) => {
if (object instanceof MyType) {
context.track(object);
return encode(object.toJSON(), { extensionCodec, context });
} else {
return null;
}
},
decode: (data, extType, context) => {
const decoded = decode(data, { extensionCodec, context });
const my = new MyType(decoded);
context.track(my);
return my;
},
});
// and later
import { encode, decode } from "@msgpack/msgpack";
const context = new MyContext();
const encoded = encode({ myType: new MyType<any>() }, { extensionCodec, context });
const decoded = decode(encoded, { extensionCodec, context });
```
### Handling BigInt with ExtensionCodec
This library does not handle BigInt by default, but you have two options to handle it:
* Set `useBigInt64: true` to map bigint to MessagePack's int64/uint64
* Define a custom `ExtensionCodec` to map bigint to a MessagePack's extension type
`useBigInt64: true` is the simplest way to handle bigint, but it has limitations:
* A bigint is encoded in 8 byte binaries even if it's a small integer
* A bigint must be smaller than the max value of the uint64 and larger than the min value of the int64. Otherwise the behavior is undefined.
So you might want to define a custom codec to handle bigint like this:
```typescript
import { deepStrictEqual } from "assert";
import { encode, decode, ExtensionCodec, DecodeError } from "@msgpack/msgpack";
// to define a custom codec:
const BIGINT_EXT_TYPE = 0; // Any in 0-127
const extensionCodec = new ExtensionCodec();
extensionCodec.register({
type: BIGINT_EXT_TYPE,
encode(input: unknown): Uint8Array | null {
if (typeof input === "bigint") {
if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) {
return encode(Number(input));
} else {
return encode(String(input));
}
} else {
return null;
}
},
decode(data: Uint8Array): bigint {
const val = decode(data);
if (!(typeof val === "string" || typeof val === "number")) {
throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`);
}
return BigInt(val);
},
});
// to use it:
const value = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1);
const encoded = encode(value, { extensionCodec });
deepStrictEqual(decode(encoded, { extensionCodec }), value);
```
### The temporal module as timestamp extensions
There is a proposal for a new date/time representations in JavaScript:
* https://github.com/tc39/proposal-temporal
This library maps `Date` to the MessagePack timestamp extension by default, but you can re-map the temporal module (or [Temporal Polyfill](https://github.com/tc39/proposal-temporal/tree/main/polyfill)) to the timestamp extension like this:
```typescript
import { Instant } from "@std-proposal/temporal";
import { deepStrictEqual } from "assert";
import {
encode,
decode,
ExtensionCodec,
EXT_TIMESTAMP,
encodeTimeSpecToTimestamp,
decodeTimestampToTimeSpec,
} from "@msgpack/msgpack";
// to define a custom codec
const extensionCodec = new ExtensionCodec();
extensionCodec.register({
type: EXT_TIMESTAMP, // override the default behavior!
encode(input: unknown): Uint8Array | null {
if (input instanceof Instant) {
const sec = input.seconds;
const nsec = Number(input.nanoseconds - BigInt(sec) * BigInt(1e9));
return encodeTimeSpecToTimestamp({ sec, nsec });
} else {
return null;
}
},
decode(data: Uint8Array): Instant {
const timeSpec = decodeTimestampToTimeSpec(data);
const sec = BigInt(timeSpec.sec);
const nsec = BigInt(timeSpec.nsec);
return Instant.fromEpochNanoseconds(sec * BigInt(1e9) + nsec);
},
});
// to use it
const instant = Instant.fromEpochMilliseconds(Date.now());
const encoded = encode(instant, { extensionCodec });
const decoded = decode(encoded, { extensionCodec });
deepStrictEqual(decoded, instant);
```
This will become default in this library with major-version increment, if the temporal module is standardized.
## Faster way to decode a large array of floating point numbers
If there are large arrays of floating point numbers in your payload, there
is a way to decode it faster: define a custom extension type for `Float#Array`
with alignment.
An extension type's `encode` method can return a function that takes a parameter
`pos: number`. This parameter can be used to make alignment of the buffer,
resulting decoding it much more performant.
See an example implementation for `Float32Array`:
```typescript
const extensionCodec = new ExtensionCodec();
const EXT_TYPE_FLOAT32ARRAY = 0; // Any in 0-127
extensionCodec.register({
type: EXT_TYPE_FLOAT32ARRAY,
encode: (object: unknown) => {
if (object instanceof Float32Array) {
return (pos: number) => {
const bpe = Float32Array.BYTES_PER_ELEMENT;
const padding = 1 + ((bpe - ((pos + 1) % bpe)) % bpe);
const data = new Uint8Array(object.buffer);
const result = new Uint8Array(padding + data.length);
result[0] = padding;
result.set(data, padding);
return result;
};
}
return null;
},
decode: (data: Uint8Array) => {
const padding = data[0]!;
const bpe = Float32Array.BYTES_PER_ELEMENT;
const offset = data.byteOffset + padding;
const length = data.byteLength - padding;
return new Float32Array(data.buffer, offset, length / bpe);
},
});
```
## Decoding a Blob
[`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) is a binary data container provided by browsers. To read its contents when it contains a MessagePack binary, you can use `Blob#arrayBuffer()` or `Blob#stream()`. `Blob#stream()`
is recommended if your target platform support it. This is because streaming
decode should be faster for large objects. In both ways, you need to use
asynchronous API.
```typescript
async function decodeFromBlob(blob: Blob): unknown {
if (blob.stream) {
// Blob#stream(): ReadableStream<Uint8Array> (recommended)
return await decodeAsync(blob.stream());
} else {
// Blob#arrayBuffer(): Promise<ArrayBuffer> (if stream() is not available)
return decode(await blob.arrayBuffer());
}
}
```
## MessagePack Specification
This library is compatible with the "August 2017" revision of MessagePack specification at the point where timestamp ext was added:
* [x] str/bin separation, added at August 2013
* [x] extension types, added at August 2013
* [x] timestamp ext type, added at August 2017
The living specification is here:
https://github.com/msgpack/msgpack
Note that as of June 2019 there're no official "version" on the MessagePack specification. See https://github.com/msgpack/msgpack/issues/195 for the discussions.
### MessagePack Mapping Table
The following table shows how JavaScript values are mapped to [MessagePack formats](https://github.com/msgpack/msgpack/blob/master/spec.md) and vice versa.
The mapping of integers varies on the setting of `useBigInt64`.
The default, `useBigInt64: false` is:
| Source Value | MessagePack Format | Value Decoded |
| --------------------- | -------------------- | --------------------- |
| null, undefined | nil | null (*1) |
| boolean (true, false) | bool family | boolean (true, false) |
| number (53-bit int) | int family | number |
| number (64-bit float) | float family | number |
| string | str family | string (*2) |
| ArrayBufferView | bin family | Uint8Array (*3) |
| Array | array family | Array |
| Object | map family | Object (*4) |
| Date | timestamp ext family | Date (*5) |
| bigint | N/A | N/A (*6) |
* *1 Both `null` and `undefined` are mapped to `nil` (`0xC0`) type, and are decoded into `null`
* *2 If you'd like to skip UTF-8 decoding of strings, set `rawStrings: true`. In this case, strings are decoded into `Uint8Array`.
* *3 Any `ArrayBufferView`s including NodeJS's `Buffer` are mapped to `bin` family, and are decoded into `Uint8Array`
* *4 In handling `Object`, it is regarded as `Record<string, unknown>` in terms of TypeScript
* *5 MessagePack timestamps may have nanoseconds, which will lost when it is decoded into JavaScript `Date`. This behavior can be overridden by registering `-1` for the extension codec.
* *6 bigint is not supported in `useBigInt64: false` mode, but you can define an extension codec for it.
If you set `useBigInt64: true`, the following mapping is used:
| Source Value | MessagePack Format | Value Decoded |
| --------------------------------- | -------------------- | --------------------- |
| null, undefined | nil | null |
| boolean (true, false) | bool family | boolean (true, false) |
| **number (32-bit int)** | int family | number |
| **number (except for the above)** | float family | number |
| **bigint** | int64 / uint64 | bigint (*7) |
| string | str family | string |
| ArrayBufferView | bin family | Uint8Array |
| Array | array family | Array |
| Object | map family | Object |
| Date | timestamp ext family | Date |
* *7 If the bigint is larger than the max value of uint64 or smaller than the min value of int64, then the behavior is undefined.
## Prerequisites
This is a universal JavaScript library that supports major browsers and NodeJS.
### ECMA-262
* ES2015 language features
* ES2024 standard library, including:
* Typed arrays (ES2015)
* Async iterations (ES2018)
* Features added in ES2015-ES2022
* whatwg encodings (`TextEncoder` and `TextDecoder`)
ES2022 standard library used in this library can be polyfilled with [core-js](https://github.com/zloirock/core-js).
IE11 is no longer supported. If you'd like to use this library in IE11, use v2.x versions.
### NodeJS
NodeJS v18 is required.
### TypeScript Compiler / Type Definitions
This module requires type definitions of `AsyncIterator`, `ArrayBufferLike`, whatwg streams, and so on. They are provided by `"lib": ["ES2024", "DOM"]` in `tsconfig.json`.
Regarding the TypeScript compiler version, only the latest TypeScript is tested in development.
## Benchmark
Run-time performance is not the only reason to use MessagePack, but it's important to choose MessagePack libraries, so a benchmark suite is provided to monitor the performance of this library.
V8's built-in JSON has been improved for years, esp. `JSON.parse()` is [significantly improved in V8/7.6](https://v8.dev/blog/v8-release-76), it is the fastest deserializer as of 2019, as the benchmark result bellow suggests.
However, MessagePack can handles binary data effectively, actual performance depends on situations. Esp. streaming-decoding may be significantly faster than non-streaming decoding if it's effective. You'd better take benchmark on your own use-case if performance matters.
Benchmark on NodeJS/v22.13.1 (V8/12.4)
| operation | op | ms | op/s |
| ------------------------------------------------- | ------: | ---: | -----: |
| buf = Buffer.from(JSON.stringify(obj)); | 1348700 | 5000 | 269740 |
| obj = JSON.parse(buf.toString("utf-8")); | 1700300 | 5000 | 340060 |
| buf = require("msgpack-lite").encode(obj); | 591300 | 5000 | 118260 |
| obj = require("msgpack-lite").decode(buf); | 539500 | 5000 | 107900 |
| buf = require("@msgpack/msgpack").encode(obj); | 1238700 | 5000 | 247740 |
| obj = require("@msgpack/msgpack").decode(buf); | 1402000 | 5000 | 280400 |
| buf = /* @msgpack/msgpack */ encoder.encode(obj); | 1379800 | 5000 | 275960 |
| obj = /* @msgpack/msgpack */ decoder.decode(buf); | 1406100 | 5000 | 281220 |
Note that `JSON` cases use `Buffer` to emulate I/O where a JavaScript string must be converted into a byte array encoded in UTF-8, whereas MessagePack modules deal with byte arrays.
## Distribution
### NPM / npmjs.com
The NPM package distributed in npmjs.com includes both ES2015+ and ES5 files:
* `dist/` is compiled into ES2020 with CommomJS, provided for NodeJS v10
* `dist.umd/` is compiled into ES5 with UMD
* `dist.umd/msgpack.min.js` - the minified file
* `dist.umd/msgpack.js` - the non-minified file
* `dist.esm/` is compiled into ES2020 with ES modules, provided for webpack-like bundlers and NodeJS's ESM-mode
If you use NodeJS and/or webpack, their module resolvers use the suitable one automatically.
### CDN / unpkg.com
This library is available via CDN:
```html
<script crossorigin src="https://unpkg.com/@msgpack/msgpack"></script>
```
It loads `MessagePack` module to the global object.
## Deno Support
You can use this module on Deno.
See `example/deno-*.ts` for examples.
`deno.land/x` is not supported.
## Bun Support
You can use this module on Bun.
## Maintenance
### Testing
For simple testing:
```
npm run test
```
### Continuous Integration
This library uses GitHub Actions.
Test matrix:
* NodeJS
* v18 / v20 / v22
* Browsers:
* Chrome, Firefox
* Deno
* Bun
### Release Engineering
```console
# run tests on NodeJS, Chrome, and Firefox
make test-all
# edit the changelog
code CHANGELOG.md
# bump version
npm version patch|minor|major
# run the publishing task
make publish
```
### Updating Dependencies
```console
npm run update-dependencies
```
## License
Copyright 2019 The MessagePack community.
This software uses the ISC license:
https://opensource.org/licenses/ISC
See [LICENSE](./LICENSE) for details.
+66
View File
@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CachedKeyDecoder = void 0;
const utf8_ts_1 = require("./utils/utf8.cjs");;
const DEFAULT_MAX_KEY_LENGTH = 16;
const DEFAULT_MAX_LENGTH_PER_KEY = 16;
class CachedKeyDecoder {
hit = 0;
miss = 0;
caches;
maxKeyLength;
maxLengthPerKey;
constructor(maxKeyLength = DEFAULT_MAX_KEY_LENGTH, maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY) {
this.maxKeyLength = maxKeyLength;
this.maxLengthPerKey = maxLengthPerKey;
// avoid `new Array(N)`, which makes a sparse array,
// because a sparse array is typically slower than a non-sparse array.
this.caches = [];
for (let i = 0; i < this.maxKeyLength; i++) {
this.caches.push([]);
}
}
canBeCached(byteLength) {
return byteLength > 0 && byteLength <= this.maxKeyLength;
}
find(bytes, inputOffset, byteLength) {
const records = this.caches[byteLength - 1];
FIND_CHUNK: for (const record of records) {
const recordBytes = record.bytes;
for (let j = 0; j < byteLength; j++) {
if (recordBytes[j] !== bytes[inputOffset + j]) {
continue FIND_CHUNK;
}
}
return record.str;
}
return null;
}
store(bytes, value) {
const records = this.caches[bytes.length - 1];
const record = { bytes, str: value };
if (records.length >= this.maxLengthPerKey) {
// `records` are full!
// Set `record` to an arbitrary position.
records[(Math.random() * records.length) | 0] = record;
}
else {
records.push(record);
}
}
decode(bytes, inputOffset, byteLength) {
const cachedValue = this.find(bytes, inputOffset, byteLength);
if (cachedValue != null) {
this.hit++;
return cachedValue;
}
this.miss++;
const str = (0, utf8_ts_1.utf8DecodeJs)(bytes, inputOffset, byteLength);
// Ensure to copy a slice of bytes because the bytes may be a NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.
const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength);
this.store(slicedCopyOfBytes, str);
return str;
}
}
exports.CachedKeyDecoder = CachedKeyDecoder;
//# sourceMappingURL=CachedKeyDecoder.cjs.map
@@ -0,0 +1 @@
{"version":3,"file":"CachedKeyDecodercjs","sourceRoot":"","sources":["../src/CachedKeyDecoder.ts"],"names":[],"mappings":";;;AAAA,6CAA+C;AAE/C,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAClC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAWtC;IACE,GAAG,GAAG,CAAC,CAAC;IACR,IAAI,GAAG,CAAC,CAAC;IACQ,MAAM,CAA+B;IAC7C,YAAY,CAAS;IACrB,eAAe,CAAS;IAEjC,YAAY,YAAY,GAAG,sBAAsB,EAAE,eAAe,GAAG,0BAA0B,EAAE;QAC/F,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QAEvC,oDAAoD;QACpD,sEAAsE;QACtE,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC;IAAA,CACF;IAEM,WAAW,CAAC,UAAkB,EAAW;QAC9C,OAAO,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,IAAI,CAAC,YAAY,CAAC;IAAA,CAC1D;IAEO,IAAI,CAAC,KAAiB,EAAE,WAAmB,EAAE,UAAkB,EAAiB;QACtF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,CAAE,CAAC;QAE7C,UAAU,EAAE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YACzC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBACpC,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC9C,SAAS,UAAU,CAAC;gBACtB,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC,GAAG,CAAC;QACpB,CAAC;QACD,OAAO,IAAI,CAAC;IAAA,CACb;IAEO,KAAK,CAAC,KAAiB,EAAE,KAAa,EAAE;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QAC/C,MAAM,MAAM,GAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QAErD,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC3C,sBAAsB;YACtB,yCAAyC;YACzC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IAAA,CACF;IAEM,MAAM,CAAC,KAAiB,EAAE,WAAmB,EAAE,UAAkB,EAAU;QAChF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QAC9D,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;QAEZ,MAAM,GAAG,GAAG,IAAA,sBAAY,EAAC,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;QACzD,+IAA+I;QAC/I,MAAM,iBAAiB,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,GAAG,UAAU,CAAC,CAAC;QACxG,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,GAAG,CAAC;IAAA,CACZ;CACF"}
+18
View File
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DecodeError = void 0;
class DecodeError extends Error {
constructor(message) {
super(message);
// fix the prototype chain in a cross-platform way
const proto = Object.create(DecodeError.prototype);
Object.setPrototypeOf(this, proto);
Object.defineProperty(this, "name", {
configurable: true,
enumerable: false,
value: DecodeError.name,
});
}
}
exports.DecodeError = DecodeError;
//# sourceMappingURL=DecodeError.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"DecodeErrorcjs","sourceRoot":"","sources":["../src/DecodeError.ts"],"names":[],"mappings":";;;AAAA,iBAAyB,SAAQ,KAAK;IACpC,YAAY,OAAe,EAAE;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,kDAAkD;QAClD,MAAM,KAAK,GAAiC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACjF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAEnC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE;YAClC,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,WAAW,CAAC,IAAI;SACxB,CAAC,CAAC;IAAA,CACJ;CACF"}
+738
View File
@@ -0,0 +1,738 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Decoder = void 0;
const prettyByte_ts_1 = require("./utils/prettyByte.cjs");;
const ExtensionCodec_ts_1 = require("./ExtensionCodec.cjs");;
const int_ts_1 = require("./utils/int.cjs");;
const utf8_ts_1 = require("./utils/utf8.cjs");;
const typedArrays_ts_1 = require("./utils/typedArrays.cjs");;
const CachedKeyDecoder_ts_1 = require("./CachedKeyDecoder.cjs");;
const DecodeError_ts_1 = require("./DecodeError.cjs");;
const STATE_ARRAY = "array";
const STATE_MAP_KEY = "map_key";
const STATE_MAP_VALUE = "map_value";
const mapKeyConverter = (key) => {
if (typeof key === "string" || typeof key === "number") {
return key;
}
throw new DecodeError_ts_1.DecodeError("The type of key must be string or number but " + typeof key);
};
class StackPool {
stack = [];
stackHeadPosition = -1;
get length() {
return this.stackHeadPosition + 1;
}
top() {
return this.stack[this.stackHeadPosition];
}
pushArrayState(size) {
const state = this.getUninitializedStateFromPool();
state.type = STATE_ARRAY;
state.position = 0;
state.size = size;
state.array = new Array(size);
}
pushMapState(size) {
const state = this.getUninitializedStateFromPool();
state.type = STATE_MAP_KEY;
state.readCount = 0;
state.size = size;
state.map = {};
}
getUninitializedStateFromPool() {
this.stackHeadPosition++;
if (this.stackHeadPosition === this.stack.length) {
const partialState = {
type: undefined,
size: 0,
array: undefined,
position: 0,
readCount: 0,
map: undefined,
key: null,
};
this.stack.push(partialState);
}
return this.stack[this.stackHeadPosition];
}
release(state) {
const topStackState = this.stack[this.stackHeadPosition];
if (topStackState !== state) {
throw new Error("Invalid stack state. Released state is not on top of the stack.");
}
if (state.type === STATE_ARRAY) {
const partialState = state;
partialState.size = 0;
partialState.array = undefined;
partialState.position = 0;
partialState.type = undefined;
}
if (state.type === STATE_MAP_KEY || state.type === STATE_MAP_VALUE) {
const partialState = state;
partialState.size = 0;
partialState.map = undefined;
partialState.readCount = 0;
partialState.type = undefined;
}
this.stackHeadPosition--;
}
reset() {
this.stack.length = 0;
this.stackHeadPosition = -1;
}
}
const HEAD_BYTE_REQUIRED = -1;
const EMPTY_VIEW = new DataView(new ArrayBuffer(0));
const EMPTY_BYTES = new Uint8Array(EMPTY_VIEW.buffer);
try {
// IE11: The spec says it should throw RangeError,
// IE11: but in IE11 it throws TypeError.
EMPTY_VIEW.getInt8(0);
}
catch (e) {
if (!(e instanceof RangeError)) {
throw new Error("This module is not supported in the current JavaScript engine because DataView does not throw RangeError on out-of-bounds access");
}
}
const MORE_DATA = new RangeError("Insufficient data");
const sharedCachedKeyDecoder = new CachedKeyDecoder_ts_1.CachedKeyDecoder();
class Decoder {
extensionCodec;
context;
useBigInt64;
rawStrings;
maxStrLength;
maxBinLength;
maxArrayLength;
maxMapLength;
maxExtLength;
keyDecoder;
mapKeyConverter;
totalPos = 0;
pos = 0;
view = EMPTY_VIEW;
bytes = EMPTY_BYTES;
headByte = HEAD_BYTE_REQUIRED;
stack = new StackPool();
entered = false;
constructor(options) {
this.extensionCodec = options?.extensionCodec ?? ExtensionCodec_ts_1.ExtensionCodec.defaultCodec;
this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined
this.useBigInt64 = options?.useBigInt64 ?? false;
this.rawStrings = options?.rawStrings ?? false;
this.maxStrLength = options?.maxStrLength ?? int_ts_1.UINT32_MAX;
this.maxBinLength = options?.maxBinLength ?? int_ts_1.UINT32_MAX;
this.maxArrayLength = options?.maxArrayLength ?? int_ts_1.UINT32_MAX;
this.maxMapLength = options?.maxMapLength ?? int_ts_1.UINT32_MAX;
this.maxExtLength = options?.maxExtLength ?? int_ts_1.UINT32_MAX;
this.keyDecoder = options?.keyDecoder !== undefined ? options.keyDecoder : sharedCachedKeyDecoder;
this.mapKeyConverter = options?.mapKeyConverter ?? mapKeyConverter;
}
clone() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return new Decoder({
extensionCodec: this.extensionCodec,
context: this.context,
useBigInt64: this.useBigInt64,
rawStrings: this.rawStrings,
maxStrLength: this.maxStrLength,
maxBinLength: this.maxBinLength,
maxArrayLength: this.maxArrayLength,
maxMapLength: this.maxMapLength,
maxExtLength: this.maxExtLength,
keyDecoder: this.keyDecoder,
});
}
reinitializeState() {
this.totalPos = 0;
this.headByte = HEAD_BYTE_REQUIRED;
this.stack.reset();
// view, bytes, and pos will be re-initialized in setBuffer()
}
setBuffer(buffer) {
const bytes = (0, typedArrays_ts_1.ensureUint8Array)(buffer);
this.bytes = bytes;
this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
this.pos = 0;
}
appendBuffer(buffer) {
if (this.headByte === HEAD_BYTE_REQUIRED && !this.hasRemaining(1)) {
this.setBuffer(buffer);
}
else {
const remainingData = this.bytes.subarray(this.pos);
const newData = (0, typedArrays_ts_1.ensureUint8Array)(buffer);
// concat remainingData + newData
const newBuffer = new Uint8Array(remainingData.length + newData.length);
newBuffer.set(remainingData);
newBuffer.set(newData, remainingData.length);
this.setBuffer(newBuffer);
}
}
hasRemaining(size) {
return this.view.byteLength - this.pos >= size;
}
createExtraByteError(posToShow) {
const { view, pos } = this;
return new RangeError(`Extra ${view.byteLength - pos} of ${view.byteLength} byte(s) found at buffer[${posToShow}]`);
}
/**
* @throws {@link DecodeError}
* @throws {@link RangeError}
*/
decode(buffer) {
if (this.entered) {
const instance = this.clone();
return instance.decode(buffer);
}
try {
this.entered = true;
this.reinitializeState();
this.setBuffer(buffer);
const object = this.doDecodeSync();
if (this.hasRemaining(1)) {
throw this.createExtraByteError(this.pos);
}
return object;
}
finally {
this.entered = false;
}
}
*decodeMulti(buffer) {
if (this.entered) {
const instance = this.clone();
yield* instance.decodeMulti(buffer);
return;
}
try {
this.entered = true;
this.reinitializeState();
this.setBuffer(buffer);
while (this.hasRemaining(1)) {
yield this.doDecodeSync();
}
}
finally {
this.entered = false;
}
}
async decodeAsync(stream) {
if (this.entered) {
const instance = this.clone();
return instance.decodeAsync(stream);
}
try {
this.entered = true;
let decoded = false;
let object;
for await (const buffer of stream) {
if (decoded) {
this.entered = false;
throw this.createExtraByteError(this.totalPos);
}
this.appendBuffer(buffer);
try {
object = this.doDecodeSync();
decoded = true;
}
catch (e) {
if (!(e instanceof RangeError)) {
throw e; // rethrow
}
// fallthrough
}
this.totalPos += this.pos;
}
if (decoded) {
if (this.hasRemaining(1)) {
throw this.createExtraByteError(this.totalPos);
}
return object;
}
const { headByte, pos, totalPos } = this;
throw new RangeError(`Insufficient data in parsing ${(0, prettyByte_ts_1.prettyByte)(headByte)} at ${totalPos} (${pos} in the current buffer)`);
}
finally {
this.entered = false;
}
}
decodeArrayStream(stream) {
return this.decodeMultiAsync(stream, true);
}
decodeStream(stream) {
return this.decodeMultiAsync(stream, false);
}
async *decodeMultiAsync(stream, isArray) {
if (this.entered) {
const instance = this.clone();
yield* instance.decodeMultiAsync(stream, isArray);
return;
}
try {
this.entered = true;
let isArrayHeaderRequired = isArray;
let arrayItemsLeft = -1;
for await (const buffer of stream) {
if (isArray && arrayItemsLeft === 0) {
throw this.createExtraByteError(this.totalPos);
}
this.appendBuffer(buffer);
if (isArrayHeaderRequired) {
arrayItemsLeft = this.readArraySize();
isArrayHeaderRequired = false;
this.complete();
}
try {
while (true) {
yield this.doDecodeSync();
if (--arrayItemsLeft === 0) {
break;
}
}
}
catch (e) {
if (!(e instanceof RangeError)) {
throw e; // rethrow
}
// fallthrough
}
this.totalPos += this.pos;
}
}
finally {
this.entered = false;
}
}
doDecodeSync() {
DECODE: while (true) {
const headByte = this.readHeadByte();
let object;
if (headByte >= 0xe0) {
// negative fixint (111x xxxx) 0xe0 - 0xff
object = headByte - 0x100;
}
else if (headByte < 0xc0) {
if (headByte < 0x80) {
// positive fixint (0xxx xxxx) 0x00 - 0x7f
object = headByte;
}
else if (headByte < 0x90) {
// fixmap (1000 xxxx) 0x80 - 0x8f
const size = headByte - 0x80;
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte < 0xa0) {
// fixarray (1001 xxxx) 0x90 - 0x9f
const size = headByte - 0x90;
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else {
// fixstr (101x xxxx) 0xa0 - 0xbf
const byteLength = headByte - 0xa0;
object = this.decodeString(byteLength, 0);
}
}
else if (headByte === 0xc0) {
// nil
object = null;
}
else if (headByte === 0xc2) {
// false
object = false;
}
else if (headByte === 0xc3) {
// true
object = true;
}
else if (headByte === 0xca) {
// float 32
object = this.readF32();
}
else if (headByte === 0xcb) {
// float 64
object = this.readF64();
}
else if (headByte === 0xcc) {
// uint 8
object = this.readU8();
}
else if (headByte === 0xcd) {
// uint 16
object = this.readU16();
}
else if (headByte === 0xce) {
// uint 32
object = this.readU32();
}
else if (headByte === 0xcf) {
// uint 64
if (this.useBigInt64) {
object = this.readU64AsBigInt();
}
else {
object = this.readU64();
}
}
else if (headByte === 0xd0) {
// int 8
object = this.readI8();
}
else if (headByte === 0xd1) {
// int 16
object = this.readI16();
}
else if (headByte === 0xd2) {
// int 32
object = this.readI32();
}
else if (headByte === 0xd3) {
// int 64
if (this.useBigInt64) {
object = this.readI64AsBigInt();
}
else {
object = this.readI64();
}
}
else if (headByte === 0xd9) {
// str 8
const byteLength = this.lookU8();
object = this.decodeString(byteLength, 1);
}
else if (headByte === 0xda) {
// str 16
const byteLength = this.lookU16();
object = this.decodeString(byteLength, 2);
}
else if (headByte === 0xdb) {
// str 32
const byteLength = this.lookU32();
object = this.decodeString(byteLength, 4);
}
else if (headByte === 0xdc) {
// array 16
const size = this.readU16();
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else if (headByte === 0xdd) {
// array 32
const size = this.readU32();
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else if (headByte === 0xde) {
// map 16
const size = this.readU16();
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte === 0xdf) {
// map 32
const size = this.readU32();
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte === 0xc4) {
// bin 8
const size = this.lookU8();
object = this.decodeBinary(size, 1);
}
else if (headByte === 0xc5) {
// bin 16
const size = this.lookU16();
object = this.decodeBinary(size, 2);
}
else if (headByte === 0xc6) {
// bin 32
const size = this.lookU32();
object = this.decodeBinary(size, 4);
}
else if (headByte === 0xd4) {
// fixext 1
object = this.decodeExtension(1, 0);
}
else if (headByte === 0xd5) {
// fixext 2
object = this.decodeExtension(2, 0);
}
else if (headByte === 0xd6) {
// fixext 4
object = this.decodeExtension(4, 0);
}
else if (headByte === 0xd7) {
// fixext 8
object = this.decodeExtension(8, 0);
}
else if (headByte === 0xd8) {
// fixext 16
object = this.decodeExtension(16, 0);
}
else if (headByte === 0xc7) {
// ext 8
const size = this.lookU8();
object = this.decodeExtension(size, 1);
}
else if (headByte === 0xc8) {
// ext 16
const size = this.lookU16();
object = this.decodeExtension(size, 2);
}
else if (headByte === 0xc9) {
// ext 32
const size = this.lookU32();
object = this.decodeExtension(size, 4);
}
else {
throw new DecodeError_ts_1.DecodeError(`Unrecognized type byte: ${(0, prettyByte_ts_1.prettyByte)(headByte)}`);
}
this.complete();
const stack = this.stack;
while (stack.length > 0) {
// arrays and maps
const state = stack.top();
if (state.type === STATE_ARRAY) {
state.array[state.position] = object;
state.position++;
if (state.position === state.size) {
object = state.array;
stack.release(state);
}
else {
continue DECODE;
}
}
else if (state.type === STATE_MAP_KEY) {
if (object === "__proto__") {
throw new DecodeError_ts_1.DecodeError("The key __proto__ is not allowed");
}
state.key = this.mapKeyConverter(object);
state.type = STATE_MAP_VALUE;
continue DECODE;
}
else {
// it must be `state.type === State.MAP_VALUE` here
state.map[state.key] = object;
state.readCount++;
if (state.readCount === state.size) {
object = state.map;
stack.release(state);
}
else {
state.key = null;
state.type = STATE_MAP_KEY;
continue DECODE;
}
}
}
return object;
}
}
readHeadByte() {
if (this.headByte === HEAD_BYTE_REQUIRED) {
this.headByte = this.readU8();
// console.log("headByte", prettyByte(this.headByte));
}
return this.headByte;
}
complete() {
this.headByte = HEAD_BYTE_REQUIRED;
}
readArraySize() {
const headByte = this.readHeadByte();
switch (headByte) {
case 0xdc:
return this.readU16();
case 0xdd:
return this.readU32();
default: {
if (headByte < 0xa0) {
return headByte - 0x90;
}
else {
throw new DecodeError_ts_1.DecodeError(`Unrecognized array type byte: ${(0, prettyByte_ts_1.prettyByte)(headByte)}`);
}
}
}
}
pushMapState(size) {
if (size > this.maxMapLength) {
throw new DecodeError_ts_1.DecodeError(`Max length exceeded: map length (${size}) > maxMapLengthLength (${this.maxMapLength})`);
}
this.stack.pushMapState(size);
}
pushArrayState(size) {
if (size > this.maxArrayLength) {
throw new DecodeError_ts_1.DecodeError(`Max length exceeded: array length (${size}) > maxArrayLength (${this.maxArrayLength})`);
}
this.stack.pushArrayState(size);
}
decodeString(byteLength, headerOffset) {
if (!this.rawStrings || this.stateIsMapKey()) {
return this.decodeUtf8String(byteLength, headerOffset);
}
return this.decodeBinary(byteLength, headerOffset);
}
/**
* @throws {@link RangeError}
*/
decodeUtf8String(byteLength, headerOffset) {
if (byteLength > this.maxStrLength) {
throw new DecodeError_ts_1.DecodeError(`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`);
}
if (this.bytes.byteLength < this.pos + headerOffset + byteLength) {
throw MORE_DATA;
}
const offset = this.pos + headerOffset;
let object;
if (this.stateIsMapKey() && this.keyDecoder?.canBeCached(byteLength)) {
object = this.keyDecoder.decode(this.bytes, offset, byteLength);
}
else {
object = (0, utf8_ts_1.utf8Decode)(this.bytes, offset, byteLength);
}
this.pos += headerOffset + byteLength;
return object;
}
stateIsMapKey() {
if (this.stack.length > 0) {
const state = this.stack.top();
return state.type === STATE_MAP_KEY;
}
return false;
}
/**
* @throws {@link RangeError}
*/
decodeBinary(byteLength, headOffset) {
if (byteLength > this.maxBinLength) {
throw new DecodeError_ts_1.DecodeError(`Max length exceeded: bin length (${byteLength}) > maxBinLength (${this.maxBinLength})`);
}
if (!this.hasRemaining(byteLength + headOffset)) {
throw MORE_DATA;
}
const offset = this.pos + headOffset;
const object = this.bytes.subarray(offset, offset + byteLength);
this.pos += headOffset + byteLength;
return object;
}
decodeExtension(size, headOffset) {
if (size > this.maxExtLength) {
throw new DecodeError_ts_1.DecodeError(`Max length exceeded: ext length (${size}) > maxExtLength (${this.maxExtLength})`);
}
const extType = this.view.getInt8(this.pos + headOffset);
const data = this.decodeBinary(size, headOffset + 1 /* extType */);
return this.extensionCodec.decode(data, extType, this.context);
}
lookU8() {
return this.view.getUint8(this.pos);
}
lookU16() {
return this.view.getUint16(this.pos);
}
lookU32() {
return this.view.getUint32(this.pos);
}
readU8() {
const value = this.view.getUint8(this.pos);
this.pos++;
return value;
}
readI8() {
const value = this.view.getInt8(this.pos);
this.pos++;
return value;
}
readU16() {
const value = this.view.getUint16(this.pos);
this.pos += 2;
return value;
}
readI16() {
const value = this.view.getInt16(this.pos);
this.pos += 2;
return value;
}
readU32() {
const value = this.view.getUint32(this.pos);
this.pos += 4;
return value;
}
readI32() {
const value = this.view.getInt32(this.pos);
this.pos += 4;
return value;
}
readU64() {
const value = (0, int_ts_1.getUint64)(this.view, this.pos);
this.pos += 8;
return value;
}
readI64() {
const value = (0, int_ts_1.getInt64)(this.view, this.pos);
this.pos += 8;
return value;
}
readU64AsBigInt() {
const value = this.view.getBigUint64(this.pos);
this.pos += 8;
return value;
}
readI64AsBigInt() {
const value = this.view.getBigInt64(this.pos);
this.pos += 8;
return value;
}
readF32() {
const value = this.view.getFloat32(this.pos);
this.pos += 4;
return value;
}
readF64() {
const value = this.view.getFloat64(this.pos);
this.pos += 8;
return value;
}
}
exports.Decoder = Decoder;
//# sourceMappingURL=Decoder.cjs.map
File diff suppressed because one or more lines are too long
+498
View File
@@ -0,0 +1,498 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Encoder = exports.DEFAULT_INITIAL_BUFFER_SIZE = exports.DEFAULT_MAX_DEPTH = void 0;
const utf8_ts_1 = require("./utils/utf8.cjs");;
const ExtensionCodec_ts_1 = require("./ExtensionCodec.cjs");;
const int_ts_1 = require("./utils/int.cjs");;
const typedArrays_ts_1 = require("./utils/typedArrays.cjs");;
exports.DEFAULT_MAX_DEPTH = 100;
exports.DEFAULT_INITIAL_BUFFER_SIZE = 2048;
class Encoder {
extensionCodec;
context;
useBigInt64;
maxDepth;
initialBufferSize;
sortKeys;
forceFloat32;
ignoreUndefined;
forceIntegerToFloat;
pos;
view;
bytes;
entered = false;
constructor(options) {
this.extensionCodec = options?.extensionCodec ?? ExtensionCodec_ts_1.ExtensionCodec.defaultCodec;
this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined
this.useBigInt64 = options?.useBigInt64 ?? false;
this.maxDepth = options?.maxDepth ?? exports.DEFAULT_MAX_DEPTH;
this.initialBufferSize = options?.initialBufferSize ?? exports.DEFAULT_INITIAL_BUFFER_SIZE;
this.sortKeys = options?.sortKeys ?? false;
this.forceFloat32 = options?.forceFloat32 ?? false;
this.ignoreUndefined = options?.ignoreUndefined ?? false;
this.forceIntegerToFloat = options?.forceIntegerToFloat ?? false;
this.pos = 0;
this.view = new DataView(new ArrayBuffer(this.initialBufferSize));
this.bytes = new Uint8Array(this.view.buffer);
}
clone() {
// Because of slightly special argument `context`,
// type assertion is needed.
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return new Encoder({
extensionCodec: this.extensionCodec,
context: this.context,
useBigInt64: this.useBigInt64,
maxDepth: this.maxDepth,
initialBufferSize: this.initialBufferSize,
sortKeys: this.sortKeys,
forceFloat32: this.forceFloat32,
ignoreUndefined: this.ignoreUndefined,
forceIntegerToFloat: this.forceIntegerToFloat,
});
}
reinitializeState() {
this.pos = 0;
}
/**
* This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}.
*
* @returns Encodes the object and returns a shared reference the encoder's internal buffer.
*/
encodeSharedRef(object) {
if (this.entered) {
const instance = this.clone();
return instance.encodeSharedRef(object);
}
try {
this.entered = true;
this.reinitializeState();
this.doEncode(object, 1);
return this.bytes.subarray(0, this.pos);
}
finally {
this.entered = false;
}
}
/**
* @returns Encodes the object and returns a copy of the encoder's internal buffer.
*/
encode(object) {
if (this.entered) {
const instance = this.clone();
return instance.encode(object);
}
try {
this.entered = true;
this.reinitializeState();
this.doEncode(object, 1);
return this.bytes.slice(0, this.pos);
}
finally {
this.entered = false;
}
}
doEncode(object, depth) {
if (depth > this.maxDepth) {
throw new Error(`Too deep objects in depth ${depth}`);
}
if (object == null) {
this.encodeNil();
}
else if (typeof object === "boolean") {
this.encodeBoolean(object);
}
else if (typeof object === "number") {
if (!this.forceIntegerToFloat) {
this.encodeNumber(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
else if (typeof object === "string") {
this.encodeString(object);
}
else if (this.useBigInt64 && typeof object === "bigint") {
this.encodeBigInt64(object);
}
else {
this.encodeObject(object, depth);
}
}
ensureBufferSizeToWrite(sizeToWrite) {
const requiredSize = this.pos + sizeToWrite;
if (this.view.byteLength < requiredSize) {
this.resizeBuffer(requiredSize * 2);
}
}
resizeBuffer(newSize) {
const newBuffer = new ArrayBuffer(newSize);
const newBytes = new Uint8Array(newBuffer);
const newView = new DataView(newBuffer);
newBytes.set(this.bytes);
this.view = newView;
this.bytes = newBytes;
}
encodeNil() {
this.writeU8(0xc0);
}
encodeBoolean(object) {
if (object === false) {
this.writeU8(0xc2);
}
else {
this.writeU8(0xc3);
}
}
encodeNumber(object) {
if (!this.forceIntegerToFloat && Number.isSafeInteger(object)) {
if (object >= 0) {
if (object < 0x80) {
// positive fixint
this.writeU8(object);
}
else if (object < 0x100) {
// uint 8
this.writeU8(0xcc);
this.writeU8(object);
}
else if (object < 0x10000) {
// uint 16
this.writeU8(0xcd);
this.writeU16(object);
}
else if (object < 0x100000000) {
// uint 32
this.writeU8(0xce);
this.writeU32(object);
}
else if (!this.useBigInt64) {
// uint 64
this.writeU8(0xcf);
this.writeU64(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
else {
if (object >= -0x20) {
// negative fixint
this.writeU8(0xe0 | (object + 0x20));
}
else if (object >= -0x80) {
// int 8
this.writeU8(0xd0);
this.writeI8(object);
}
else if (object >= -0x8000) {
// int 16
this.writeU8(0xd1);
this.writeI16(object);
}
else if (object >= -0x80000000) {
// int 32
this.writeU8(0xd2);
this.writeI32(object);
}
else if (!this.useBigInt64) {
// int 64
this.writeU8(0xd3);
this.writeI64(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
}
else {
this.encodeNumberAsFloat(object);
}
}
encodeNumberAsFloat(object) {
if (this.forceFloat32) {
// float 32
this.writeU8(0xca);
this.writeF32(object);
}
else {
// float 64
this.writeU8(0xcb);
this.writeF64(object);
}
}
encodeBigInt64(object) {
if (object >= BigInt(0)) {
// uint 64
this.writeU8(0xcf);
this.writeBigUint64(object);
}
else {
// int 64
this.writeU8(0xd3);
this.writeBigInt64(object);
}
}
writeStringHeader(byteLength) {
if (byteLength < 32) {
// fixstr
this.writeU8(0xa0 + byteLength);
}
else if (byteLength < 0x100) {
// str 8
this.writeU8(0xd9);
this.writeU8(byteLength);
}
else if (byteLength < 0x10000) {
// str 16
this.writeU8(0xda);
this.writeU16(byteLength);
}
else if (byteLength < 0x100000000) {
// str 32
this.writeU8(0xdb);
this.writeU32(byteLength);
}
else {
throw new Error(`Too long string: ${byteLength} bytes in UTF-8`);
}
}
encodeString(object) {
const maxHeaderSize = 1 + 4;
const byteLength = (0, utf8_ts_1.utf8Count)(object);
this.ensureBufferSizeToWrite(maxHeaderSize + byteLength);
this.writeStringHeader(byteLength);
(0, utf8_ts_1.utf8Encode)(object, this.bytes, this.pos);
this.pos += byteLength;
}
encodeObject(object, depth) {
// try to encode objects with custom codec first of non-primitives
const ext = this.extensionCodec.tryToEncode(object, this.context);
if (ext != null) {
this.encodeExtension(ext);
}
else if (Array.isArray(object)) {
this.encodeArray(object, depth);
}
else if (ArrayBuffer.isView(object)) {
this.encodeBinary(object);
}
else if (typeof object === "object") {
this.encodeMap(object, depth);
}
else {
// symbol, function and other special object come here unless extensionCodec handles them.
throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(object)}`);
}
}
encodeBinary(object) {
const size = object.byteLength;
if (size < 0x100) {
// bin 8
this.writeU8(0xc4);
this.writeU8(size);
}
else if (size < 0x10000) {
// bin 16
this.writeU8(0xc5);
this.writeU16(size);
}
else if (size < 0x100000000) {
// bin 32
this.writeU8(0xc6);
this.writeU32(size);
}
else {
throw new Error(`Too large binary: ${size}`);
}
const bytes = (0, typedArrays_ts_1.ensureUint8Array)(object);
this.writeU8a(bytes);
}
encodeArray(object, depth) {
const size = object.length;
if (size < 16) {
// fixarray
this.writeU8(0x90 + size);
}
else if (size < 0x10000) {
// array 16
this.writeU8(0xdc);
this.writeU16(size);
}
else if (size < 0x100000000) {
// array 32
this.writeU8(0xdd);
this.writeU32(size);
}
else {
throw new Error(`Too large array: ${size}`);
}
for (const item of object) {
this.doEncode(item, depth + 1);
}
}
countWithoutUndefined(object, keys) {
let count = 0;
for (const key of keys) {
if (object[key] !== undefined) {
count++;
}
}
return count;
}
encodeMap(object, depth) {
const keys = Object.keys(object);
if (this.sortKeys) {
keys.sort();
}
const size = this.ignoreUndefined ? this.countWithoutUndefined(object, keys) : keys.length;
if (size < 16) {
// fixmap
this.writeU8(0x80 + size);
}
else if (size < 0x10000) {
// map 16
this.writeU8(0xde);
this.writeU16(size);
}
else if (size < 0x100000000) {
// map 32
this.writeU8(0xdf);
this.writeU32(size);
}
else {
throw new Error(`Too large map object: ${size}`);
}
for (const key of keys) {
const value = object[key];
if (!(this.ignoreUndefined && value === undefined)) {
this.encodeString(key);
this.doEncode(value, depth + 1);
}
}
}
encodeExtension(ext) {
if (typeof ext.data === "function") {
const data = ext.data(this.pos + 6);
const size = data.length;
if (size >= 0x100000000) {
throw new Error(`Too large extension object: ${size}`);
}
this.writeU8(0xc9);
this.writeU32(size);
this.writeI8(ext.type);
this.writeU8a(data);
return;
}
const size = ext.data.length;
if (size === 1) {
// fixext 1
this.writeU8(0xd4);
}
else if (size === 2) {
// fixext 2
this.writeU8(0xd5);
}
else if (size === 4) {
// fixext 4
this.writeU8(0xd6);
}
else if (size === 8) {
// fixext 8
this.writeU8(0xd7);
}
else if (size === 16) {
// fixext 16
this.writeU8(0xd8);
}
else if (size < 0x100) {
// ext 8
this.writeU8(0xc7);
this.writeU8(size);
}
else if (size < 0x10000) {
// ext 16
this.writeU8(0xc8);
this.writeU16(size);
}
else if (size < 0x100000000) {
// ext 32
this.writeU8(0xc9);
this.writeU32(size);
}
else {
throw new Error(`Too large extension object: ${size}`);
}
this.writeI8(ext.type);
this.writeU8a(ext.data);
}
writeU8(value) {
this.ensureBufferSizeToWrite(1);
this.view.setUint8(this.pos, value);
this.pos++;
}
writeU8a(values) {
const size = values.length;
this.ensureBufferSizeToWrite(size);
this.bytes.set(values, this.pos);
this.pos += size;
}
writeI8(value) {
this.ensureBufferSizeToWrite(1);
this.view.setInt8(this.pos, value);
this.pos++;
}
writeU16(value) {
this.ensureBufferSizeToWrite(2);
this.view.setUint16(this.pos, value);
this.pos += 2;
}
writeI16(value) {
this.ensureBufferSizeToWrite(2);
this.view.setInt16(this.pos, value);
this.pos += 2;
}
writeU32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setUint32(this.pos, value);
this.pos += 4;
}
writeI32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setInt32(this.pos, value);
this.pos += 4;
}
writeF32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setFloat32(this.pos, value);
this.pos += 4;
}
writeF64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setFloat64(this.pos, value);
this.pos += 8;
}
writeU64(value) {
this.ensureBufferSizeToWrite(8);
(0, int_ts_1.setUint64)(this.view, this.pos, value);
this.pos += 8;
}
writeI64(value) {
this.ensureBufferSizeToWrite(8);
(0, int_ts_1.setInt64)(this.view, this.pos, value);
this.pos += 8;
}
writeBigUint64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setBigUint64(this.pos, value);
this.pos += 8;
}
writeBigInt64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setBigInt64(this.pos, value);
this.pos += 8;
}
}
exports.Encoder = Encoder;
//# sourceMappingURL=Encoder.cjs.map
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtData = void 0;
/**
* ExtData is used to handle Extension Types that are not registered to ExtensionCodec.
*/
class ExtData {
type;
data;
constructor(type, data) {
this.type = type;
this.data = data;
}
}
exports.ExtData = ExtData;
//# sourceMappingURL=ExtData.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ExtDatacjs","sourceRoot":"","sources":["../src/ExtData.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH;IACW,IAAI,CAAS;IACb,IAAI,CAA6C;IAE1D,YAAY,IAAY,EAAE,IAAgD,EAAE;QAC1E,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CAClB;CACF"}
+76
View File
@@ -0,0 +1,76 @@
"use strict";
// ExtensionCodec to handle MessagePack extensions
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionCodec = void 0;
const ExtData_ts_1 = require("./ExtData.cjs");;
const timestamp_ts_1 = require("./timestamp.cjs");;
class ExtensionCodec {
static defaultCodec = new ExtensionCodec();
// ensures ExtensionCodecType<X> matches ExtensionCodec<X>
// this will make type errors a lot more clear
// eslint-disable-next-line @typescript-eslint/naming-convention
__brand;
// built-in extensions
builtInEncoders = [];
builtInDecoders = [];
// custom extensions
encoders = [];
decoders = [];
constructor() {
this.register(timestamp_ts_1.timestampExtension);
}
register({ type, encode, decode, }) {
if (type >= 0) {
// custom extensions
this.encoders[type] = encode;
this.decoders[type] = decode;
}
else {
// built-in extensions
const index = -1 - type;
this.builtInEncoders[index] = encode;
this.builtInDecoders[index] = decode;
}
}
tryToEncode(object, context) {
// built-in extensions
for (let i = 0; i < this.builtInEncoders.length; i++) {
const encodeExt = this.builtInEncoders[i];
if (encodeExt != null) {
const data = encodeExt(object, context);
if (data != null) {
const type = -1 - i;
return new ExtData_ts_1.ExtData(type, data);
}
}
}
// custom extensions
for (let i = 0; i < this.encoders.length; i++) {
const encodeExt = this.encoders[i];
if (encodeExt != null) {
const data = encodeExt(object, context);
if (data != null) {
const type = i;
return new ExtData_ts_1.ExtData(type, data);
}
}
}
if (object instanceof ExtData_ts_1.ExtData) {
// to keep ExtData as is
return object;
}
return null;
}
decode(data, type, context) {
const decodeExt = type < 0 ? this.builtInDecoders[-1 - type] : this.decoders[type];
if (decodeExt) {
return decodeExt(data, type, context);
}
else {
// decode() does not fail, returns ExtData instead.
return new ExtData_ts_1.ExtData(type, data);
}
}
}
exports.ExtensionCodec = ExtensionCodec;
//# sourceMappingURL=ExtensionCodec.cjs.map
@@ -0,0 +1 @@
{"version":3,"file":"ExtensionCodeccjs","sourceRoot":"","sources":["../src/ExtensionCodec.ts"],"names":[],"mappings":"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"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=context.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"contextcjs","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":""}
+30
View File
@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = decode;
exports.decodeMulti = decodeMulti;
const Decoder_ts_1 = require("./Decoder.cjs");;
/**
* It decodes a single MessagePack object in a buffer.
*
* This is a synchronous decoding function.
* See other variants for asynchronous decoding: {@link decodeAsync}, {@link decodeMultiStream}, or {@link decodeArrayStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
function decode(buffer, options) {
const decoder = new Decoder_ts_1.Decoder(options);
return decoder.decode(buffer);
}
/**
* It decodes multiple MessagePack objects in a buffer.
* This is corresponding to {@link decodeMultiStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
function decodeMulti(buffer, options) {
const decoder = new Decoder_ts_1.Decoder(options);
return decoder.decodeMulti(buffer);
}
//# sourceMappingURL=decode.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"decodecjs","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":";;;;AAAA,6CAAuC;AAIvC;;;;;;;;GAQG;AACH,gBACE,MAA6D,EAC7D,OAAqD,EAC5C;IACT,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAAA,CAC/B;AAED;;;;;;GAMG;AACH,qBACE,MAAwC,EACxC,OAAqD,EAClB;IACnC,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AAAA,CACpC"}
+35
View File
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeAsync = decodeAsync;
exports.decodeArrayStream = decodeArrayStream;
exports.decodeMultiStream = decodeMultiStream;
const Decoder_ts_1 = require("./Decoder.cjs");;
const stream_ts_1 = require("./utils/stream.cjs");;
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
async function decodeAsync(streamLike, options) {
const stream = (0, stream_ts_1.ensureAsyncIterable)(streamLike);
const decoder = new Decoder_ts_1.Decoder(options);
return decoder.decodeAsync(stream);
}
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
function decodeArrayStream(streamLike, options) {
const stream = (0, stream_ts_1.ensureAsyncIterable)(streamLike);
const decoder = new Decoder_ts_1.Decoder(options);
return decoder.decodeArrayStream(stream);
}
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
function decodeMultiStream(streamLike, options) {
const stream = (0, stream_ts_1.ensureAsyncIterable)(streamLike);
const decoder = new Decoder_ts_1.Decoder(options);
return decoder.decodeStream(stream);
}
//# sourceMappingURL=decodeAsync.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"decodeAsynccjs","sourceRoot":"","sources":["../src/decodeAsync.ts"],"names":[],"mappings":";;;;;AAAA,6CAAuC;AACvC,iDAAwD;AAKxD;;;GAGG;AACI,KAAK,sBACV,UAAgE,EAChE,OAAqD,EACnC;IAClB,MAAM,MAAM,GAAG,IAAA,+BAAmB,EAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AAAA,CACpC;AAED;;;GAGG;AACH,2BACE,UAAgE,EAChE,OAAqD,EACb;IACxC,MAAM,MAAM,GAAG,IAAA,+BAAmB,EAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAAA,CAC1C;AAED;;;GAGG;AACH,2BACE,UAAgE,EAChE,OAAqD,EACb;IACxC,MAAM,MAAM,GAAG,IAAA,+BAAmB,EAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,CACrC"}
+15
View File
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.encode = encode;
const Encoder_ts_1 = require("./Encoder.cjs");;
/**
* It encodes `value` in the MessagePack format and
* returns a byte buffer.
*
* The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`.
*/
function encode(value, options) {
const encoder = new Encoder_ts_1.Encoder(options);
return encoder.encodeSharedRef(value);
}
//# sourceMappingURL=encode.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"encodecjs","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":";;;AAAA,6CAAuC;AAIvC;;;;;GAKG;AACH,gBACE,KAAc,EACd,OAAqD,EAC5B;IACzB,MAAM,OAAO,GAAG,IAAI,oBAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;AAAA,CACvC"}
+32
View File
@@ -0,0 +1,32 @@
"use strict";
// Main Functions:
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeTimestampExtension = exports.encodeTimestampExtension = exports.decodeTimestampToTimeSpec = exports.encodeTimeSpecToTimestamp = exports.encodeDateToTimeSpec = exports.EXT_TIMESTAMP = exports.ExtData = exports.ExtensionCodec = exports.Encoder = exports.DecodeError = exports.Decoder = exports.decodeMultiStream = exports.decodeArrayStream = exports.decodeAsync = exports.decodeMulti = exports.decode = exports.encode = void 0;
const encode_ts_1 = require("./encode.cjs");;
Object.defineProperty(exports, "encode", { enumerable: true, get: function () { return encode_ts_1.encode; } });
const decode_ts_1 = require("./decode.cjs");;
Object.defineProperty(exports, "decode", { enumerable: true, get: function () { return decode_ts_1.decode; } });
Object.defineProperty(exports, "decodeMulti", { enumerable: true, get: function () { return decode_ts_1.decodeMulti; } });
const decodeAsync_ts_1 = require("./decodeAsync.cjs");;
Object.defineProperty(exports, "decodeAsync", { enumerable: true, get: function () { return decodeAsync_ts_1.decodeAsync; } });
Object.defineProperty(exports, "decodeArrayStream", { enumerable: true, get: function () { return decodeAsync_ts_1.decodeArrayStream; } });
Object.defineProperty(exports, "decodeMultiStream", { enumerable: true, get: function () { return decodeAsync_ts_1.decodeMultiStream; } });
const Decoder_ts_1 = require("./Decoder.cjs");;
Object.defineProperty(exports, "Decoder", { enumerable: true, get: function () { return Decoder_ts_1.Decoder; } });
const DecodeError_ts_1 = require("./DecodeError.cjs");;
Object.defineProperty(exports, "DecodeError", { enumerable: true, get: function () { return DecodeError_ts_1.DecodeError; } });
const Encoder_ts_1 = require("./Encoder.cjs");;
Object.defineProperty(exports, "Encoder", { enumerable: true, get: function () { return Encoder_ts_1.Encoder; } });
// Utilities for Extension Types:
const ExtensionCodec_ts_1 = require("./ExtensionCodec.cjs");;
Object.defineProperty(exports, "ExtensionCodec", { enumerable: true, get: function () { return ExtensionCodec_ts_1.ExtensionCodec; } });
const ExtData_ts_1 = require("./ExtData.cjs");;
Object.defineProperty(exports, "ExtData", { enumerable: true, get: function () { return ExtData_ts_1.ExtData; } });
const timestamp_ts_1 = require("./timestamp.cjs");;
Object.defineProperty(exports, "EXT_TIMESTAMP", { enumerable: true, get: function () { return timestamp_ts_1.EXT_TIMESTAMP; } });
Object.defineProperty(exports, "encodeDateToTimeSpec", { enumerable: true, get: function () { return timestamp_ts_1.encodeDateToTimeSpec; } });
Object.defineProperty(exports, "encodeTimeSpecToTimestamp", { enumerable: true, get: function () { return timestamp_ts_1.encodeTimeSpecToTimestamp; } });
Object.defineProperty(exports, "decodeTimestampToTimeSpec", { enumerable: true, get: function () { return timestamp_ts_1.decodeTimestampToTimeSpec; } });
Object.defineProperty(exports, "encodeTimestampExtension", { enumerable: true, get: function () { return timestamp_ts_1.encodeTimestampExtension; } });
Object.defineProperty(exports, "decodeTimestampExtension", { enumerable: true, get: function () { return timestamp_ts_1.decodeTimestampExtension; } });
//# sourceMappingURL=index.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"indexcjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,kBAAkB;;;AAElB,2CAAqC;uFAA5B,kBAAM;AAGf,2CAAkD;uFAAzC,kBAAM;4FAAE,uBAAW;AAG5B,qDAAqF;4FAA5E,4BAAW;kGAAE,kCAAiB;kGAAE,kCAAiB;AAG1D,6CAAuC;wFAA9B,oBAAO;AAIhB,qDAA+C;4FAAtC,4BAAW;AAGpB,6CAAuC;wFAA9B,oBAAO;AAKhB,iCAAiC;AAEjC,2DAAqD;+FAA5C,kCAAc;AAIvB,6CAAuC;wFAA9B,oBAAO;AAGhB,iDAOwB;8FANtB,4BAAa;qGACb,mCAAoB;0GACpB,wCAAyB;0GACzB,wCAAyB;yGACzB,uCAAwB;yGACxB,uCAAwB"}
+104
View File
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.timestampExtension = exports.EXT_TIMESTAMP = void 0;
exports.encodeTimeSpecToTimestamp = encodeTimeSpecToTimestamp;
exports.encodeDateToTimeSpec = encodeDateToTimeSpec;
exports.encodeTimestampExtension = encodeTimestampExtension;
exports.decodeTimestampToTimeSpec = decodeTimestampToTimeSpec;
exports.decodeTimestampExtension = decodeTimestampExtension;
// https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type
const DecodeError_ts_1 = require("./DecodeError.cjs");;
const int_ts_1 = require("./utils/int.cjs");;
exports.EXT_TIMESTAMP = -1;
const TIMESTAMP32_MAX_SEC = 0x100000000 - 1; // 32-bit unsigned int
const TIMESTAMP64_MAX_SEC = 0x400000000 - 1; // 34-bit unsigned int
function encodeTimeSpecToTimestamp({ sec, nsec }) {
if (sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC) {
// Here sec >= 0 && nsec >= 0
if (nsec === 0 && sec <= TIMESTAMP32_MAX_SEC) {
// timestamp 32 = { sec32 (unsigned) }
const rv = new Uint8Array(4);
const view = new DataView(rv.buffer);
view.setUint32(0, sec);
return rv;
}
else {
// timestamp 64 = { nsec30 (unsigned), sec34 (unsigned) }
const secHigh = sec / 0x100000000;
const secLow = sec & 0xffffffff;
const rv = new Uint8Array(8);
const view = new DataView(rv.buffer);
// nsec30 | secHigh2
view.setUint32(0, (nsec << 2) | (secHigh & 0x3));
// secLow32
view.setUint32(4, secLow);
return rv;
}
}
else {
// timestamp 96 = { nsec32 (unsigned), sec64 (signed) }
const rv = new Uint8Array(12);
const view = new DataView(rv.buffer);
view.setUint32(0, nsec);
(0, int_ts_1.setInt64)(view, 4, sec);
return rv;
}
}
function encodeDateToTimeSpec(date) {
const msec = date.getTime();
const sec = Math.floor(msec / 1e3);
const nsec = (msec - sec * 1e3) * 1e6;
// Normalizes { sec, nsec } to ensure nsec is unsigned.
const nsecInSec = Math.floor(nsec / 1e9);
return {
sec: sec + nsecInSec,
nsec: nsec - nsecInSec * 1e9,
};
}
function encodeTimestampExtension(object) {
if (object instanceof Date) {
const timeSpec = encodeDateToTimeSpec(object);
return encodeTimeSpecToTimestamp(timeSpec);
}
else {
return null;
}
}
function decodeTimestampToTimeSpec(data) {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
// data may be 32, 64, or 96 bits
switch (data.byteLength) {
case 4: {
// timestamp 32 = { sec32 }
const sec = view.getUint32(0);
const nsec = 0;
return { sec, nsec };
}
case 8: {
// timestamp 64 = { nsec30, sec34 }
const nsec30AndSecHigh2 = view.getUint32(0);
const secLow32 = view.getUint32(4);
const sec = (nsec30AndSecHigh2 & 0x3) * 0x100000000 + secLow32;
const nsec = nsec30AndSecHigh2 >>> 2;
return { sec, nsec };
}
case 12: {
// timestamp 96 = { nsec32 (unsigned), sec64 (signed) }
const sec = (0, int_ts_1.getInt64)(view, 4);
const nsec = view.getUint32(0);
return { sec, nsec };
}
default:
throw new DecodeError_ts_1.DecodeError(`Unrecognized data size for timestamp (expected 4, 8, or 12): ${data.length}`);
}
}
function decodeTimestampExtension(data) {
const timeSpec = decodeTimestampToTimeSpec(data);
return new Date(timeSpec.sec * 1e3 + timeSpec.nsec / 1e6);
}
exports.timestampExtension = {
type: exports.EXT_TIMESTAMP,
encode: encodeTimestampExtension,
decode: decodeTimestampExtension,
};
//# sourceMappingURL=timestamp.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"timestampcjs","sourceRoot":"","sources":["../src/timestamp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
{"version":"7.0.0-dev.20251225.1","root":["../src/cachedkeydecoder.ts","../src/decodeerror.ts","../src/decoder.ts","../src/encoder.ts","../src/extdata.ts","../src/extensioncodec.ts","../src/context.ts","../src/decode.ts","../src/decodeasync.ts","../src/encode.ts","../src/index.ts","../src/timestamp.ts","../src/utils/int.ts","../src/utils/prettybyte.ts","../src/utils/stream.ts","../src/utils/typedarrays.ts","../src/utils/utf8.ts"]}
+34
View File
@@ -0,0 +1,34 @@
"use strict";
// Integer Utility
Object.defineProperty(exports, "__esModule", { value: true });
exports.UINT32_MAX = void 0;
exports.setUint64 = setUint64;
exports.setInt64 = setInt64;
exports.getInt64 = getInt64;
exports.getUint64 = getUint64;
exports.UINT32_MAX = 4294967295;
// DataView extension to handle int64 / uint64,
// where the actual range is 53-bits integer (a.k.a. safe integer)
function setUint64(view, offset, value) {
const high = value / 4294967296;
const low = value; // high bits are truncated by DataView
view.setUint32(offset, high);
view.setUint32(offset + 4, low);
}
function setInt64(view, offset, value) {
const high = Math.floor(value / 4294967296);
const low = value; // high bits are truncated by DataView
view.setUint32(offset, high);
view.setUint32(offset + 4, low);
}
function getInt64(view, offset) {
const high = view.getInt32(offset);
const low = view.getUint32(offset + 4);
return high * 4294967296 + low;
}
function getUint64(view, offset) {
const high = view.getUint32(offset);
const low = view.getUint32(offset + 4);
return high * 4294967296 + low;
}
//# sourceMappingURL=int.cjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"intcjs","sourceRoot":"","sources":["../../src/utils/int.ts"],"names":[],"mappings":";AAAA,kBAAkB;;;;;;;AAEL,QAAA,UAAU,GAAG,UAAW,CAAC;AAEtC,+CAA+C;AAC/C,kEAAkE;AAElE,mBAA0B,IAAc,EAAE,MAAc,EAAE,KAAa,EAAQ;IAC7E,MAAM,IAAI,GAAG,KAAK,GAAG,UAAa,CAAC;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,sCAAsC;IACzD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAAA,CACjC;AAED,kBAAyB,IAAc,EAAE,MAAc,EAAE,KAAa,EAAQ;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,UAAa,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,sCAAsC;IACzD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAAA,CACjC;AAED,kBAAyB,IAAc,EAAE,MAAc,EAAU;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,UAAa,GAAG,GAAG,CAAC;AAAA,CACnC;AAED,mBAA0B,IAAc,EAAE,MAAc,EAAU;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,UAAa,GAAG,GAAG,CAAC;AAAA,CACnC"}
@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.prettyByte = prettyByte;
function prettyByte(byte) {
return `${byte < 0 ? "-" : ""}0x${Math.abs(byte).toString(16).padStart(2, "0")}`;
}
//# sourceMappingURL=prettyByte.cjs.map
@@ -0,0 +1 @@
{"version":3,"file":"prettyBytecjs","sourceRoot":"","sources":["../../src/utils/prettyByte.ts"],"names":[],"mappings":";;;AAAA,oBAA2B,IAAY,EAAU;IAC/C,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAAA,CAClF"}
+33
View File
@@ -0,0 +1,33 @@
"use strict";
// utility for whatwg streams
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAsyncIterable = isAsyncIterable;
exports.asyncIterableFromStream = asyncIterableFromStream;
exports.ensureAsyncIterable = ensureAsyncIterable;
function isAsyncIterable(object) {
return object[Symbol.asyncIterator] != null;
}
async function* asyncIterableFromStream(stream) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
return;
}
yield value;
}
}
finally {
reader.releaseLock();
}
}
function ensureAsyncIterable(streamLike) {
if (isAsyncIterable(streamLike)) {
return streamLike;
}
else {
return asyncIterableFromStream(streamLike);
}
}
//# sourceMappingURL=stream.cjs.map
@@ -0,0 +1 @@
{"version":3,"file":"streamcjs","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":";AAAA,6BAA6B;;;;;AAQ7B,yBAAmC,MAA6B,EAA8B;IAC5F,OAAQ,MAAc,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC;AAAA,CACtD;AAEM,KAAK,SAAS,CAAC,yBAA4B,MAAyB,EAAoB;IAC7F,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAElC,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AAAA,CACF;AAED,6BAAuC,UAAiC,EAAoB;IAC1F,IAAI,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,UAAU,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;AAAA,CACF"}
+22
View File
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureUint8Array = ensureUint8Array;
function isArrayBufferLike(buffer) {
return (buffer instanceof ArrayBuffer || (typeof SharedArrayBuffer !== "undefined" && buffer instanceof SharedArrayBuffer));
}
function ensureUint8Array(buffer) {
if (buffer instanceof Uint8Array) {
return buffer;
}
else if (ArrayBuffer.isView(buffer)) {
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
}
else if (isArrayBufferLike(buffer)) {
return new Uint8Array(buffer);
}
else {
// ArrayLike<number>
return Uint8Array.from(buffer);
}
}
//# sourceMappingURL=typedArrays.cjs.map
@@ -0,0 +1 @@
{"version":3,"file":"typedArrayscjs","sourceRoot":"","sources":["../../src/utils/typedArrays.ts"],"names":[],"mappings":";;;AAAA,SAAS,iBAAiB,CAAC,MAAe,EAA6B;IACrE,OAAO,CACL,MAAM,YAAY,WAAW,IAAI,CAAC,OAAO,iBAAiB,KAAK,WAAW,IAAI,MAAM,YAAY,iBAAiB,CAAC,CACnH,CAAC;AAAA,CACH;AAED,0BACE,MAA2F,EAC9D;IAC7B,IAAI,MAAM,YAAY,UAAU,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;SAAM,IAAI,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC7E,CAAC;SAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,oBAAoB;QACpB,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;AAAA,CACF"}
+177
View File
@@ -0,0 +1,177 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.utf8Count = utf8Count;
exports.utf8EncodeJs = utf8EncodeJs;
exports.utf8EncodeTE = utf8EncodeTE;
exports.utf8Encode = utf8Encode;
exports.utf8DecodeJs = utf8DecodeJs;
exports.utf8DecodeTD = utf8DecodeTD;
exports.utf8Decode = utf8Decode;
function utf8Count(str) {
const strLength = str.length;
let byteLength = 0;
let pos = 0;
while (pos < strLength) {
let value = str.charCodeAt(pos++);
if ((value & 0xffffff80) === 0) {
// 1-byte
byteLength++;
continue;
}
else if ((value & 0xfffff800) === 0) {
// 2-bytes
byteLength += 2;
}
else {
// handle surrogate pair
if (value >= 0xd800 && value <= 0xdbff) {
// high surrogate
if (pos < strLength) {
const extra = str.charCodeAt(pos);
if ((extra & 0xfc00) === 0xdc00) {
++pos;
value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
}
}
}
if ((value & 0xffff0000) === 0) {
// 3-byte
byteLength += 3;
}
else {
// 4-byte
byteLength += 4;
}
}
}
return byteLength;
}
function utf8EncodeJs(str, output, outputOffset) {
const strLength = str.length;
let offset = outputOffset;
let pos = 0;
while (pos < strLength) {
let value = str.charCodeAt(pos++);
if ((value & 0xffffff80) === 0) {
// 1-byte
output[offset++] = value;
continue;
}
else if ((value & 0xfffff800) === 0) {
// 2-bytes
output[offset++] = ((value >> 6) & 0x1f) | 0xc0;
}
else {
// handle surrogate pair
if (value >= 0xd800 && value <= 0xdbff) {
// high surrogate
if (pos < strLength) {
const extra = str.charCodeAt(pos);
if ((extra & 0xfc00) === 0xdc00) {
++pos;
value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
}
}
}
if ((value & 0xffff0000) === 0) {
// 3-byte
output[offset++] = ((value >> 12) & 0x0f) | 0xe0;
output[offset++] = ((value >> 6) & 0x3f) | 0x80;
}
else {
// 4-byte
output[offset++] = ((value >> 18) & 0x07) | 0xf0;
output[offset++] = ((value >> 12) & 0x3f) | 0x80;
output[offset++] = ((value >> 6) & 0x3f) | 0x80;
}
}
output[offset++] = (value & 0x3f) | 0x80;
}
}
// TextEncoder and TextDecoder are standardized in whatwg encoding:
// https://encoding.spec.whatwg.org/
// and available in all the modern browsers:
// https://caniuse.com/textencoder
// They are available in Node.js since v12 LTS as well:
// https://nodejs.org/api/globals.html#textencoder
const sharedTextEncoder = new TextEncoder();
// This threshold should be determined by benchmarking, which might vary in engines and input data.
// Run `npx ts-node benchmark/encode-string.ts` for details.
const TEXT_ENCODER_THRESHOLD = 50;
function utf8EncodeTE(str, output, outputOffset) {
sharedTextEncoder.encodeInto(str, output.subarray(outputOffset));
}
function utf8Encode(str, output, outputOffset) {
if (str.length > TEXT_ENCODER_THRESHOLD) {
utf8EncodeTE(str, output, outputOffset);
}
else {
utf8EncodeJs(str, output, outputOffset);
}
}
const CHUNK_SIZE = 4096;
function utf8DecodeJs(bytes, inputOffset, byteLength) {
let offset = inputOffset;
const end = offset + byteLength;
const units = [];
let result = "";
while (offset < end) {
const byte1 = bytes[offset++];
if ((byte1 & 0x80) === 0) {
// 1 byte
units.push(byte1);
}
else if ((byte1 & 0xe0) === 0xc0) {
// 2 bytes
const byte2 = bytes[offset++] & 0x3f;
units.push(((byte1 & 0x1f) << 6) | byte2);
}
else if ((byte1 & 0xf0) === 0xe0) {
// 3 bytes
const byte2 = bytes[offset++] & 0x3f;
const byte3 = bytes[offset++] & 0x3f;
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
}
else if ((byte1 & 0xf8) === 0xf0) {
// 4 bytes
const byte2 = bytes[offset++] & 0x3f;
const byte3 = bytes[offset++] & 0x3f;
const byte4 = bytes[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 >= CHUNK_SIZE) {
result += String.fromCharCode(...units);
units.length = 0;
}
}
if (units.length > 0) {
result += String.fromCharCode(...units);
}
return result;
}
const sharedTextDecoder = new TextDecoder();
// This threshold should be determined by benchmarking, which might vary in engines and input data.
// Run `npx ts-node benchmark/decode-string.ts` for details.
const TEXT_DECODER_THRESHOLD = 200;
function utf8DecodeTD(bytes, inputOffset, byteLength) {
const stringBytes = bytes.subarray(inputOffset, inputOffset + byteLength);
return sharedTextDecoder.decode(stringBytes);
}
function utf8Decode(bytes, inputOffset, byteLength) {
if (byteLength > TEXT_DECODER_THRESHOLD) {
return utf8DecodeTD(bytes, inputOffset, byteLength);
}
else {
return utf8DecodeJs(bytes, inputOffset, byteLength);
}
}
//# sourceMappingURL=utf8.cjs.map
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
export interface KeyDecoder {
canBeCached(byteLength: number): boolean;
decode(bytes: Uint8Array, inputOffset: number, byteLength: number): string;
}
export declare class CachedKeyDecoder implements KeyDecoder {
hit: number;
miss: number;
private readonly caches;
readonly maxKeyLength: number;
readonly maxLengthPerKey: number;
constructor(maxKeyLength?: number, maxLengthPerKey?: number);
canBeCached(byteLength: number): boolean;
private find;
private store;
decode(bytes: Uint8Array, inputOffset: number, byteLength: number): string;
}
+62
View File
@@ -0,0 +1,62 @@
import { utf8DecodeJs } from "./utils/utf8.mjs";
const DEFAULT_MAX_KEY_LENGTH = 16;
const DEFAULT_MAX_LENGTH_PER_KEY = 16;
export class CachedKeyDecoder {
hit = 0;
miss = 0;
caches;
maxKeyLength;
maxLengthPerKey;
constructor(maxKeyLength = DEFAULT_MAX_KEY_LENGTH, maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY) {
this.maxKeyLength = maxKeyLength;
this.maxLengthPerKey = maxLengthPerKey;
// avoid `new Array(N)`, which makes a sparse array,
// because a sparse array is typically slower than a non-sparse array.
this.caches = [];
for (let i = 0; i < this.maxKeyLength; i++) {
this.caches.push([]);
}
}
canBeCached(byteLength) {
return byteLength > 0 && byteLength <= this.maxKeyLength;
}
find(bytes, inputOffset, byteLength) {
const records = this.caches[byteLength - 1];
FIND_CHUNK: for (const record of records) {
const recordBytes = record.bytes;
for (let j = 0; j < byteLength; j++) {
if (recordBytes[j] !== bytes[inputOffset + j]) {
continue FIND_CHUNK;
}
}
return record.str;
}
return null;
}
store(bytes, value) {
const records = this.caches[bytes.length - 1];
const record = { bytes, str: value };
if (records.length >= this.maxLengthPerKey) {
// `records` are full!
// Set `record` to an arbitrary position.
records[(Math.random() * records.length) | 0] = record;
}
else {
records.push(record);
}
}
decode(bytes, inputOffset, byteLength) {
const cachedValue = this.find(bytes, inputOffset, byteLength);
if (cachedValue != null) {
this.hit++;
return cachedValue;
}
this.miss++;
const str = utf8DecodeJs(bytes, inputOffset, byteLength);
// Ensure to copy a slice of bytes because the bytes may be a NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.
const slicedCopyOfBytes = Uint8Array.prototype.slice.call(bytes, inputOffset, inputOffset + byteLength);
this.store(slicedCopyOfBytes, str);
return str;
}
}
//# sourceMappingURL=CachedKeyDecoder.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"CachedKeyDecodermjs","sourceRoot":"","sources":["../src/CachedKeyDecoder.ts"],"names":[],"mappings":"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"}
+3
View File
@@ -0,0 +1,3 @@
export declare class DecodeError extends Error {
constructor(message: string);
}
+14
View File
@@ -0,0 +1,14 @@
export class DecodeError extends Error {
constructor(message) {
super(message);
// fix the prototype chain in a cross-platform way
const proto = Object.create(DecodeError.prototype);
Object.setPrototypeOf(this, proto);
Object.defineProperty(this, "name", {
configurable: true,
enumerable: false,
value: DecodeError.name,
});
}
}
//# sourceMappingURL=DecodeError.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"DecodeErrormjs","sourceRoot":"","sources":["../src/DecodeError.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe,EAAE;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,kDAAkD;QAClD,MAAM,KAAK,GAAiC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACjF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAEnC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE;YAClC,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;YACjB,KAAK,EAAE,WAAW,CAAC,IAAI;SACxB,CAAC,CAAC;IAAA,CACJ;CACF"}
+136
View File
@@ -0,0 +1,136 @@
import type { ContextOf } from "./context.ts";
import type { ExtensionCodecType } from "./ExtensionCodec.ts";
import type { KeyDecoder } from "./CachedKeyDecoder.ts";
export type DecoderOptions<ContextType = undefined> = Readonly<Partial<{
extensionCodec: ExtensionCodecType<ContextType>;
/**
* Decodes Int64 and Uint64 as bigint if it's set to true.
* Depends on ES2020's {@link DataView#getBigInt64} and
* {@link DataView#getBigUint64}.
*
* Defaults to false.
*/
useBigInt64: boolean;
/**
* By default, string values will be decoded as UTF-8 strings. However, if this option is true,
* string values will be returned as Uint8Arrays without additional decoding.
*
* This is useful if the strings may contain invalid UTF-8 sequences.
*
* Note that this option only applies to string values, not map keys. Additionally, when
* enabled, raw string length is limited by the maxBinLength option.
*/
rawStrings: boolean;
/**
* Maximum string length.
*
* Defaults to 4_294_967_295 (UINT32_MAX).
*/
maxStrLength: number;
/**
* Maximum binary length.
*
* Defaults to 4_294_967_295 (UINT32_MAX).
*/
maxBinLength: number;
/**
* Maximum array length.
*
* Defaults to 4_294_967_295 (UINT32_MAX).
*/
maxArrayLength: number;
/**
* Maximum map length.
*
* Defaults to 4_294_967_295 (UINT32_MAX).
*/
maxMapLength: number;
/**
* Maximum extension length.
*
* Defaults to 4_294_967_295 (UINT32_MAX).
*/
maxExtLength: number;
/**
* An object key decoder. Defaults to the shared instance of {@link CachedKeyDecoder}.
* `null` is a special value to disable the use of the key decoder at all.
*/
keyDecoder: KeyDecoder | null;
/**
* A function to convert decoded map key to a valid JS key type.
*
* Defaults to a function that throws an error if the key is not a string or a number.
*/
mapKeyConverter: (key: unknown) => MapKeyType;
}>> & ContextOf<ContextType>;
type MapKeyType = string | number;
export declare class Decoder<ContextType = undefined> {
private readonly extensionCodec;
private readonly context;
private readonly useBigInt64;
private readonly rawStrings;
private readonly maxStrLength;
private readonly maxBinLength;
private readonly maxArrayLength;
private readonly maxMapLength;
private readonly maxExtLength;
private readonly keyDecoder;
private readonly mapKeyConverter;
private totalPos;
private pos;
private view;
private bytes;
private headByte;
private readonly stack;
private entered;
constructor(options?: DecoderOptions<ContextType>);
private clone;
private reinitializeState;
private setBuffer;
private appendBuffer;
private hasRemaining;
private createExtraByteError;
/**
* @throws {@link DecodeError}
* @throws {@link RangeError}
*/
decode(buffer: ArrayLike<number> | ArrayBufferView | ArrayBufferLike): unknown;
decodeMulti(buffer: ArrayLike<number> | ArrayBufferView | ArrayBufferLike): Generator<unknown, void, unknown>;
decodeAsync(stream: AsyncIterable<ArrayLike<number> | ArrayBufferView | ArrayBufferLike>): Promise<unknown>;
decodeArrayStream(stream: AsyncIterable<ArrayLike<number> | ArrayBufferView | ArrayBufferLike>): AsyncGenerator<unknown, void, unknown>;
decodeStream(stream: AsyncIterable<ArrayLike<number> | ArrayBufferView | ArrayBufferLike>): AsyncGenerator<unknown, void, unknown>;
private decodeMultiAsync;
private doDecodeSync;
private readHeadByte;
private complete;
private readArraySize;
private pushMapState;
private pushArrayState;
private decodeString;
/**
* @throws {@link RangeError}
*/
private decodeUtf8String;
private stateIsMapKey;
/**
* @throws {@link RangeError}
*/
private decodeBinary;
private decodeExtension;
private lookU8;
private lookU16;
private lookU32;
private readU8;
private readI8;
private readU16;
private readI16;
private readU32;
private readI32;
private readU64;
private readI64;
private readU64AsBigInt;
private readI64AsBigInt;
private readF32;
private readF64;
}
export {};
+734
View File
@@ -0,0 +1,734 @@
import { prettyByte } from "./utils/prettyByte.mjs";
import { ExtensionCodec } from "./ExtensionCodec.mjs";
import { getInt64, getUint64, UINT32_MAX } from "./utils/int.mjs";
import { utf8Decode } from "./utils/utf8.mjs";
import { ensureUint8Array } from "./utils/typedArrays.mjs";
import { CachedKeyDecoder } from "./CachedKeyDecoder.mjs";
import { DecodeError } from "./DecodeError.mjs";
const STATE_ARRAY = "array";
const STATE_MAP_KEY = "map_key";
const STATE_MAP_VALUE = "map_value";
const mapKeyConverter = (key) => {
if (typeof key === "string" || typeof key === "number") {
return key;
}
throw new DecodeError("The type of key must be string or number but " + typeof key);
};
class StackPool {
stack = [];
stackHeadPosition = -1;
get length() {
return this.stackHeadPosition + 1;
}
top() {
return this.stack[this.stackHeadPosition];
}
pushArrayState(size) {
const state = this.getUninitializedStateFromPool();
state.type = STATE_ARRAY;
state.position = 0;
state.size = size;
state.array = new Array(size);
}
pushMapState(size) {
const state = this.getUninitializedStateFromPool();
state.type = STATE_MAP_KEY;
state.readCount = 0;
state.size = size;
state.map = {};
}
getUninitializedStateFromPool() {
this.stackHeadPosition++;
if (this.stackHeadPosition === this.stack.length) {
const partialState = {
type: undefined,
size: 0,
array: undefined,
position: 0,
readCount: 0,
map: undefined,
key: null,
};
this.stack.push(partialState);
}
return this.stack[this.stackHeadPosition];
}
release(state) {
const topStackState = this.stack[this.stackHeadPosition];
if (topStackState !== state) {
throw new Error("Invalid stack state. Released state is not on top of the stack.");
}
if (state.type === STATE_ARRAY) {
const partialState = state;
partialState.size = 0;
partialState.array = undefined;
partialState.position = 0;
partialState.type = undefined;
}
if (state.type === STATE_MAP_KEY || state.type === STATE_MAP_VALUE) {
const partialState = state;
partialState.size = 0;
partialState.map = undefined;
partialState.readCount = 0;
partialState.type = undefined;
}
this.stackHeadPosition--;
}
reset() {
this.stack.length = 0;
this.stackHeadPosition = -1;
}
}
const HEAD_BYTE_REQUIRED = -1;
const EMPTY_VIEW = new DataView(new ArrayBuffer(0));
const EMPTY_BYTES = new Uint8Array(EMPTY_VIEW.buffer);
try {
// IE11: The spec says it should throw RangeError,
// IE11: but in IE11 it throws TypeError.
EMPTY_VIEW.getInt8(0);
}
catch (e) {
if (!(e instanceof RangeError)) {
throw new Error("This module is not supported in the current JavaScript engine because DataView does not throw RangeError on out-of-bounds access");
}
}
const MORE_DATA = new RangeError("Insufficient data");
const sharedCachedKeyDecoder = new CachedKeyDecoder();
export class Decoder {
extensionCodec;
context;
useBigInt64;
rawStrings;
maxStrLength;
maxBinLength;
maxArrayLength;
maxMapLength;
maxExtLength;
keyDecoder;
mapKeyConverter;
totalPos = 0;
pos = 0;
view = EMPTY_VIEW;
bytes = EMPTY_BYTES;
headByte = HEAD_BYTE_REQUIRED;
stack = new StackPool();
entered = false;
constructor(options) {
this.extensionCodec = options?.extensionCodec ?? ExtensionCodec.defaultCodec;
this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined
this.useBigInt64 = options?.useBigInt64 ?? false;
this.rawStrings = options?.rawStrings ?? false;
this.maxStrLength = options?.maxStrLength ?? UINT32_MAX;
this.maxBinLength = options?.maxBinLength ?? UINT32_MAX;
this.maxArrayLength = options?.maxArrayLength ?? UINT32_MAX;
this.maxMapLength = options?.maxMapLength ?? UINT32_MAX;
this.maxExtLength = options?.maxExtLength ?? UINT32_MAX;
this.keyDecoder = options?.keyDecoder !== undefined ? options.keyDecoder : sharedCachedKeyDecoder;
this.mapKeyConverter = options?.mapKeyConverter ?? mapKeyConverter;
}
clone() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return new Decoder({
extensionCodec: this.extensionCodec,
context: this.context,
useBigInt64: this.useBigInt64,
rawStrings: this.rawStrings,
maxStrLength: this.maxStrLength,
maxBinLength: this.maxBinLength,
maxArrayLength: this.maxArrayLength,
maxMapLength: this.maxMapLength,
maxExtLength: this.maxExtLength,
keyDecoder: this.keyDecoder,
});
}
reinitializeState() {
this.totalPos = 0;
this.headByte = HEAD_BYTE_REQUIRED;
this.stack.reset();
// view, bytes, and pos will be re-initialized in setBuffer()
}
setBuffer(buffer) {
const bytes = ensureUint8Array(buffer);
this.bytes = bytes;
this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
this.pos = 0;
}
appendBuffer(buffer) {
if (this.headByte === HEAD_BYTE_REQUIRED && !this.hasRemaining(1)) {
this.setBuffer(buffer);
}
else {
const remainingData = this.bytes.subarray(this.pos);
const newData = ensureUint8Array(buffer);
// concat remainingData + newData
const newBuffer = new Uint8Array(remainingData.length + newData.length);
newBuffer.set(remainingData);
newBuffer.set(newData, remainingData.length);
this.setBuffer(newBuffer);
}
}
hasRemaining(size) {
return this.view.byteLength - this.pos >= size;
}
createExtraByteError(posToShow) {
const { view, pos } = this;
return new RangeError(`Extra ${view.byteLength - pos} of ${view.byteLength} byte(s) found at buffer[${posToShow}]`);
}
/**
* @throws {@link DecodeError}
* @throws {@link RangeError}
*/
decode(buffer) {
if (this.entered) {
const instance = this.clone();
return instance.decode(buffer);
}
try {
this.entered = true;
this.reinitializeState();
this.setBuffer(buffer);
const object = this.doDecodeSync();
if (this.hasRemaining(1)) {
throw this.createExtraByteError(this.pos);
}
return object;
}
finally {
this.entered = false;
}
}
*decodeMulti(buffer) {
if (this.entered) {
const instance = this.clone();
yield* instance.decodeMulti(buffer);
return;
}
try {
this.entered = true;
this.reinitializeState();
this.setBuffer(buffer);
while (this.hasRemaining(1)) {
yield this.doDecodeSync();
}
}
finally {
this.entered = false;
}
}
async decodeAsync(stream) {
if (this.entered) {
const instance = this.clone();
return instance.decodeAsync(stream);
}
try {
this.entered = true;
let decoded = false;
let object;
for await (const buffer of stream) {
if (decoded) {
this.entered = false;
throw this.createExtraByteError(this.totalPos);
}
this.appendBuffer(buffer);
try {
object = this.doDecodeSync();
decoded = true;
}
catch (e) {
if (!(e instanceof RangeError)) {
throw e; // rethrow
}
// fallthrough
}
this.totalPos += this.pos;
}
if (decoded) {
if (this.hasRemaining(1)) {
throw this.createExtraByteError(this.totalPos);
}
return object;
}
const { headByte, pos, totalPos } = this;
throw new RangeError(`Insufficient data in parsing ${prettyByte(headByte)} at ${totalPos} (${pos} in the current buffer)`);
}
finally {
this.entered = false;
}
}
decodeArrayStream(stream) {
return this.decodeMultiAsync(stream, true);
}
decodeStream(stream) {
return this.decodeMultiAsync(stream, false);
}
async *decodeMultiAsync(stream, isArray) {
if (this.entered) {
const instance = this.clone();
yield* instance.decodeMultiAsync(stream, isArray);
return;
}
try {
this.entered = true;
let isArrayHeaderRequired = isArray;
let arrayItemsLeft = -1;
for await (const buffer of stream) {
if (isArray && arrayItemsLeft === 0) {
throw this.createExtraByteError(this.totalPos);
}
this.appendBuffer(buffer);
if (isArrayHeaderRequired) {
arrayItemsLeft = this.readArraySize();
isArrayHeaderRequired = false;
this.complete();
}
try {
while (true) {
yield this.doDecodeSync();
if (--arrayItemsLeft === 0) {
break;
}
}
}
catch (e) {
if (!(e instanceof RangeError)) {
throw e; // rethrow
}
// fallthrough
}
this.totalPos += this.pos;
}
}
finally {
this.entered = false;
}
}
doDecodeSync() {
DECODE: while (true) {
const headByte = this.readHeadByte();
let object;
if (headByte >= 0xe0) {
// negative fixint (111x xxxx) 0xe0 - 0xff
object = headByte - 0x100;
}
else if (headByte < 0xc0) {
if (headByte < 0x80) {
// positive fixint (0xxx xxxx) 0x00 - 0x7f
object = headByte;
}
else if (headByte < 0x90) {
// fixmap (1000 xxxx) 0x80 - 0x8f
const size = headByte - 0x80;
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte < 0xa0) {
// fixarray (1001 xxxx) 0x90 - 0x9f
const size = headByte - 0x90;
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else {
// fixstr (101x xxxx) 0xa0 - 0xbf
const byteLength = headByte - 0xa0;
object = this.decodeString(byteLength, 0);
}
}
else if (headByte === 0xc0) {
// nil
object = null;
}
else if (headByte === 0xc2) {
// false
object = false;
}
else if (headByte === 0xc3) {
// true
object = true;
}
else if (headByte === 0xca) {
// float 32
object = this.readF32();
}
else if (headByte === 0xcb) {
// float 64
object = this.readF64();
}
else if (headByte === 0xcc) {
// uint 8
object = this.readU8();
}
else if (headByte === 0xcd) {
// uint 16
object = this.readU16();
}
else if (headByte === 0xce) {
// uint 32
object = this.readU32();
}
else if (headByte === 0xcf) {
// uint 64
if (this.useBigInt64) {
object = this.readU64AsBigInt();
}
else {
object = this.readU64();
}
}
else if (headByte === 0xd0) {
// int 8
object = this.readI8();
}
else if (headByte === 0xd1) {
// int 16
object = this.readI16();
}
else if (headByte === 0xd2) {
// int 32
object = this.readI32();
}
else if (headByte === 0xd3) {
// int 64
if (this.useBigInt64) {
object = this.readI64AsBigInt();
}
else {
object = this.readI64();
}
}
else if (headByte === 0xd9) {
// str 8
const byteLength = this.lookU8();
object = this.decodeString(byteLength, 1);
}
else if (headByte === 0xda) {
// str 16
const byteLength = this.lookU16();
object = this.decodeString(byteLength, 2);
}
else if (headByte === 0xdb) {
// str 32
const byteLength = this.lookU32();
object = this.decodeString(byteLength, 4);
}
else if (headByte === 0xdc) {
// array 16
const size = this.readU16();
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else if (headByte === 0xdd) {
// array 32
const size = this.readU32();
if (size !== 0) {
this.pushArrayState(size);
this.complete();
continue DECODE;
}
else {
object = [];
}
}
else if (headByte === 0xde) {
// map 16
const size = this.readU16();
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte === 0xdf) {
// map 32
const size = this.readU32();
if (size !== 0) {
this.pushMapState(size);
this.complete();
continue DECODE;
}
else {
object = {};
}
}
else if (headByte === 0xc4) {
// bin 8
const size = this.lookU8();
object = this.decodeBinary(size, 1);
}
else if (headByte === 0xc5) {
// bin 16
const size = this.lookU16();
object = this.decodeBinary(size, 2);
}
else if (headByte === 0xc6) {
// bin 32
const size = this.lookU32();
object = this.decodeBinary(size, 4);
}
else if (headByte === 0xd4) {
// fixext 1
object = this.decodeExtension(1, 0);
}
else if (headByte === 0xd5) {
// fixext 2
object = this.decodeExtension(2, 0);
}
else if (headByte === 0xd6) {
// fixext 4
object = this.decodeExtension(4, 0);
}
else if (headByte === 0xd7) {
// fixext 8
object = this.decodeExtension(8, 0);
}
else if (headByte === 0xd8) {
// fixext 16
object = this.decodeExtension(16, 0);
}
else if (headByte === 0xc7) {
// ext 8
const size = this.lookU8();
object = this.decodeExtension(size, 1);
}
else if (headByte === 0xc8) {
// ext 16
const size = this.lookU16();
object = this.decodeExtension(size, 2);
}
else if (headByte === 0xc9) {
// ext 32
const size = this.lookU32();
object = this.decodeExtension(size, 4);
}
else {
throw new DecodeError(`Unrecognized type byte: ${prettyByte(headByte)}`);
}
this.complete();
const stack = this.stack;
while (stack.length > 0) {
// arrays and maps
const state = stack.top();
if (state.type === STATE_ARRAY) {
state.array[state.position] = object;
state.position++;
if (state.position === state.size) {
object = state.array;
stack.release(state);
}
else {
continue DECODE;
}
}
else if (state.type === STATE_MAP_KEY) {
if (object === "__proto__") {
throw new DecodeError("The key __proto__ is not allowed");
}
state.key = this.mapKeyConverter(object);
state.type = STATE_MAP_VALUE;
continue DECODE;
}
else {
// it must be `state.type === State.MAP_VALUE` here
state.map[state.key] = object;
state.readCount++;
if (state.readCount === state.size) {
object = state.map;
stack.release(state);
}
else {
state.key = null;
state.type = STATE_MAP_KEY;
continue DECODE;
}
}
}
return object;
}
}
readHeadByte() {
if (this.headByte === HEAD_BYTE_REQUIRED) {
this.headByte = this.readU8();
// console.log("headByte", prettyByte(this.headByte));
}
return this.headByte;
}
complete() {
this.headByte = HEAD_BYTE_REQUIRED;
}
readArraySize() {
const headByte = this.readHeadByte();
switch (headByte) {
case 0xdc:
return this.readU16();
case 0xdd:
return this.readU32();
default: {
if (headByte < 0xa0) {
return headByte - 0x90;
}
else {
throw new DecodeError(`Unrecognized array type byte: ${prettyByte(headByte)}`);
}
}
}
}
pushMapState(size) {
if (size > this.maxMapLength) {
throw new DecodeError(`Max length exceeded: map length (${size}) > maxMapLengthLength (${this.maxMapLength})`);
}
this.stack.pushMapState(size);
}
pushArrayState(size) {
if (size > this.maxArrayLength) {
throw new DecodeError(`Max length exceeded: array length (${size}) > maxArrayLength (${this.maxArrayLength})`);
}
this.stack.pushArrayState(size);
}
decodeString(byteLength, headerOffset) {
if (!this.rawStrings || this.stateIsMapKey()) {
return this.decodeUtf8String(byteLength, headerOffset);
}
return this.decodeBinary(byteLength, headerOffset);
}
/**
* @throws {@link RangeError}
*/
decodeUtf8String(byteLength, headerOffset) {
if (byteLength > this.maxStrLength) {
throw new DecodeError(`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`);
}
if (this.bytes.byteLength < this.pos + headerOffset + byteLength) {
throw MORE_DATA;
}
const offset = this.pos + headerOffset;
let object;
if (this.stateIsMapKey() && this.keyDecoder?.canBeCached(byteLength)) {
object = this.keyDecoder.decode(this.bytes, offset, byteLength);
}
else {
object = utf8Decode(this.bytes, offset, byteLength);
}
this.pos += headerOffset + byteLength;
return object;
}
stateIsMapKey() {
if (this.stack.length > 0) {
const state = this.stack.top();
return state.type === STATE_MAP_KEY;
}
return false;
}
/**
* @throws {@link RangeError}
*/
decodeBinary(byteLength, headOffset) {
if (byteLength > this.maxBinLength) {
throw new DecodeError(`Max length exceeded: bin length (${byteLength}) > maxBinLength (${this.maxBinLength})`);
}
if (!this.hasRemaining(byteLength + headOffset)) {
throw MORE_DATA;
}
const offset = this.pos + headOffset;
const object = this.bytes.subarray(offset, offset + byteLength);
this.pos += headOffset + byteLength;
return object;
}
decodeExtension(size, headOffset) {
if (size > this.maxExtLength) {
throw new DecodeError(`Max length exceeded: ext length (${size}) > maxExtLength (${this.maxExtLength})`);
}
const extType = this.view.getInt8(this.pos + headOffset);
const data = this.decodeBinary(size, headOffset + 1 /* extType */);
return this.extensionCodec.decode(data, extType, this.context);
}
lookU8() {
return this.view.getUint8(this.pos);
}
lookU16() {
return this.view.getUint16(this.pos);
}
lookU32() {
return this.view.getUint32(this.pos);
}
readU8() {
const value = this.view.getUint8(this.pos);
this.pos++;
return value;
}
readI8() {
const value = this.view.getInt8(this.pos);
this.pos++;
return value;
}
readU16() {
const value = this.view.getUint16(this.pos);
this.pos += 2;
return value;
}
readI16() {
const value = this.view.getInt16(this.pos);
this.pos += 2;
return value;
}
readU32() {
const value = this.view.getUint32(this.pos);
this.pos += 4;
return value;
}
readI32() {
const value = this.view.getInt32(this.pos);
this.pos += 4;
return value;
}
readU64() {
const value = getUint64(this.view, this.pos);
this.pos += 8;
return value;
}
readI64() {
const value = getInt64(this.view, this.pos);
this.pos += 8;
return value;
}
readU64AsBigInt() {
const value = this.view.getBigUint64(this.pos);
this.pos += 8;
return value;
}
readI64AsBigInt() {
const value = this.view.getBigInt64(this.pos);
this.pos += 8;
return value;
}
readF32() {
const value = this.view.getFloat32(this.pos);
this.pos += 4;
return value;
}
readF64() {
const value = this.view.getFloat64(this.pos);
this.pos += 8;
return value;
}
}
//# sourceMappingURL=Decoder.mjs.map
File diff suppressed because one or more lines are too long
+114
View File
@@ -0,0 +1,114 @@
import type { ContextOf } from "./context.ts";
import type { ExtensionCodecType } from "./ExtensionCodec.ts";
export declare const DEFAULT_MAX_DEPTH = 100;
export declare const DEFAULT_INITIAL_BUFFER_SIZE = 2048;
export type EncoderOptions<ContextType = undefined> = Partial<Readonly<{
extensionCodec: ExtensionCodecType<ContextType>;
/**
* Encodes bigint as Int64 or Uint64 if it's set to true.
* {@link forceIntegerToFloat} does not affect bigint.
* Depends on ES2020's {@link DataView#setBigInt64} and
* {@link DataView#setBigUint64}.
*
* Defaults to false.
*/
useBigInt64: boolean;
/**
* The maximum depth in nested objects and arrays.
*
* Defaults to 100.
*/
maxDepth: number;
/**
* The initial size of the internal buffer.
*
* Defaults to 2048.
*/
initialBufferSize: number;
/**
* If `true`, the keys of an object is sorted. In other words, the encoded
* binary is canonical and thus comparable to another encoded binary.
*
* Defaults to `false`. If enabled, it spends more time in encoding objects.
*/
sortKeys: boolean;
/**
* If `true`, non-integer numbers are encoded in float32, not in float64 (the default).
*
* Only use it if precisions don't matter.
*
* Defaults to `false`.
*/
forceFloat32: boolean;
/**
* If `true`, an object property with `undefined` value are ignored.
* e.g. `{ foo: undefined }` will be encoded as `{}`, as `JSON.stringify()` does.
*
* Defaults to `false`. If enabled, it spends more time in encoding objects.
*/
ignoreUndefined: boolean;
/**
* If `true`, integer numbers are encoded as floating point numbers,
* with the `forceFloat32` option taken into account.
*
* Defaults to `false`.
*/
forceIntegerToFloat: boolean;
}>> & ContextOf<ContextType>;
export declare class Encoder<ContextType = undefined> {
private readonly extensionCodec;
private readonly context;
private readonly useBigInt64;
private readonly maxDepth;
private readonly initialBufferSize;
private readonly sortKeys;
private readonly forceFloat32;
private readonly ignoreUndefined;
private readonly forceIntegerToFloat;
private pos;
private view;
private bytes;
private entered;
constructor(options?: EncoderOptions<ContextType>);
private clone;
private reinitializeState;
/**
* This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}.
*
* @returns Encodes the object and returns a shared reference the encoder's internal buffer.
*/
encodeSharedRef(object: unknown): Uint8Array<ArrayBuffer>;
/**
* @returns Encodes the object and returns a copy of the encoder's internal buffer.
*/
encode(object: unknown): Uint8Array<ArrayBuffer>;
private doEncode;
private ensureBufferSizeToWrite;
private resizeBuffer;
private encodeNil;
private encodeBoolean;
private encodeNumber;
private encodeNumberAsFloat;
private encodeBigInt64;
private writeStringHeader;
private encodeString;
private encodeObject;
private encodeBinary;
private encodeArray;
private countWithoutUndefined;
private encodeMap;
private encodeExtension;
private writeU8;
private writeU8a;
private writeI8;
private writeU16;
private writeI16;
private writeU32;
private writeI32;
private writeF32;
private writeF64;
private writeU64;
private writeI64;
private writeBigUint64;
private writeBigInt64;
}
+494
View File
@@ -0,0 +1,494 @@
import { utf8Count, utf8Encode } from "./utils/utf8.mjs";
import { ExtensionCodec } from "./ExtensionCodec.mjs";
import { setInt64, setUint64 } from "./utils/int.mjs";
import { ensureUint8Array } from "./utils/typedArrays.mjs";
export const DEFAULT_MAX_DEPTH = 100;
export const DEFAULT_INITIAL_BUFFER_SIZE = 2048;
export class Encoder {
extensionCodec;
context;
useBigInt64;
maxDepth;
initialBufferSize;
sortKeys;
forceFloat32;
ignoreUndefined;
forceIntegerToFloat;
pos;
view;
bytes;
entered = false;
constructor(options) {
this.extensionCodec = options?.extensionCodec ?? ExtensionCodec.defaultCodec;
this.context = options?.context; // needs a type assertion because EncoderOptions has no context property when ContextType is undefined
this.useBigInt64 = options?.useBigInt64 ?? false;
this.maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;
this.initialBufferSize = options?.initialBufferSize ?? DEFAULT_INITIAL_BUFFER_SIZE;
this.sortKeys = options?.sortKeys ?? false;
this.forceFloat32 = options?.forceFloat32 ?? false;
this.ignoreUndefined = options?.ignoreUndefined ?? false;
this.forceIntegerToFloat = options?.forceIntegerToFloat ?? false;
this.pos = 0;
this.view = new DataView(new ArrayBuffer(this.initialBufferSize));
this.bytes = new Uint8Array(this.view.buffer);
}
clone() {
// Because of slightly special argument `context`,
// type assertion is needed.
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return new Encoder({
extensionCodec: this.extensionCodec,
context: this.context,
useBigInt64: this.useBigInt64,
maxDepth: this.maxDepth,
initialBufferSize: this.initialBufferSize,
sortKeys: this.sortKeys,
forceFloat32: this.forceFloat32,
ignoreUndefined: this.ignoreUndefined,
forceIntegerToFloat: this.forceIntegerToFloat,
});
}
reinitializeState() {
this.pos = 0;
}
/**
* This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}.
*
* @returns Encodes the object and returns a shared reference the encoder's internal buffer.
*/
encodeSharedRef(object) {
if (this.entered) {
const instance = this.clone();
return instance.encodeSharedRef(object);
}
try {
this.entered = true;
this.reinitializeState();
this.doEncode(object, 1);
return this.bytes.subarray(0, this.pos);
}
finally {
this.entered = false;
}
}
/**
* @returns Encodes the object and returns a copy of the encoder's internal buffer.
*/
encode(object) {
if (this.entered) {
const instance = this.clone();
return instance.encode(object);
}
try {
this.entered = true;
this.reinitializeState();
this.doEncode(object, 1);
return this.bytes.slice(0, this.pos);
}
finally {
this.entered = false;
}
}
doEncode(object, depth) {
if (depth > this.maxDepth) {
throw new Error(`Too deep objects in depth ${depth}`);
}
if (object == null) {
this.encodeNil();
}
else if (typeof object === "boolean") {
this.encodeBoolean(object);
}
else if (typeof object === "number") {
if (!this.forceIntegerToFloat) {
this.encodeNumber(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
else if (typeof object === "string") {
this.encodeString(object);
}
else if (this.useBigInt64 && typeof object === "bigint") {
this.encodeBigInt64(object);
}
else {
this.encodeObject(object, depth);
}
}
ensureBufferSizeToWrite(sizeToWrite) {
const requiredSize = this.pos + sizeToWrite;
if (this.view.byteLength < requiredSize) {
this.resizeBuffer(requiredSize * 2);
}
}
resizeBuffer(newSize) {
const newBuffer = new ArrayBuffer(newSize);
const newBytes = new Uint8Array(newBuffer);
const newView = new DataView(newBuffer);
newBytes.set(this.bytes);
this.view = newView;
this.bytes = newBytes;
}
encodeNil() {
this.writeU8(0xc0);
}
encodeBoolean(object) {
if (object === false) {
this.writeU8(0xc2);
}
else {
this.writeU8(0xc3);
}
}
encodeNumber(object) {
if (!this.forceIntegerToFloat && Number.isSafeInteger(object)) {
if (object >= 0) {
if (object < 0x80) {
// positive fixint
this.writeU8(object);
}
else if (object < 0x100) {
// uint 8
this.writeU8(0xcc);
this.writeU8(object);
}
else if (object < 0x10000) {
// uint 16
this.writeU8(0xcd);
this.writeU16(object);
}
else if (object < 0x100000000) {
// uint 32
this.writeU8(0xce);
this.writeU32(object);
}
else if (!this.useBigInt64) {
// uint 64
this.writeU8(0xcf);
this.writeU64(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
else {
if (object >= -0x20) {
// negative fixint
this.writeU8(0xe0 | (object + 0x20));
}
else if (object >= -0x80) {
// int 8
this.writeU8(0xd0);
this.writeI8(object);
}
else if (object >= -0x8000) {
// int 16
this.writeU8(0xd1);
this.writeI16(object);
}
else if (object >= -0x80000000) {
// int 32
this.writeU8(0xd2);
this.writeI32(object);
}
else if (!this.useBigInt64) {
// int 64
this.writeU8(0xd3);
this.writeI64(object);
}
else {
this.encodeNumberAsFloat(object);
}
}
}
else {
this.encodeNumberAsFloat(object);
}
}
encodeNumberAsFloat(object) {
if (this.forceFloat32) {
// float 32
this.writeU8(0xca);
this.writeF32(object);
}
else {
// float 64
this.writeU8(0xcb);
this.writeF64(object);
}
}
encodeBigInt64(object) {
if (object >= BigInt(0)) {
// uint 64
this.writeU8(0xcf);
this.writeBigUint64(object);
}
else {
// int 64
this.writeU8(0xd3);
this.writeBigInt64(object);
}
}
writeStringHeader(byteLength) {
if (byteLength < 32) {
// fixstr
this.writeU8(0xa0 + byteLength);
}
else if (byteLength < 0x100) {
// str 8
this.writeU8(0xd9);
this.writeU8(byteLength);
}
else if (byteLength < 0x10000) {
// str 16
this.writeU8(0xda);
this.writeU16(byteLength);
}
else if (byteLength < 0x100000000) {
// str 32
this.writeU8(0xdb);
this.writeU32(byteLength);
}
else {
throw new Error(`Too long string: ${byteLength} bytes in UTF-8`);
}
}
encodeString(object) {
const maxHeaderSize = 1 + 4;
const byteLength = utf8Count(object);
this.ensureBufferSizeToWrite(maxHeaderSize + byteLength);
this.writeStringHeader(byteLength);
utf8Encode(object, this.bytes, this.pos);
this.pos += byteLength;
}
encodeObject(object, depth) {
// try to encode objects with custom codec first of non-primitives
const ext = this.extensionCodec.tryToEncode(object, this.context);
if (ext != null) {
this.encodeExtension(ext);
}
else if (Array.isArray(object)) {
this.encodeArray(object, depth);
}
else if (ArrayBuffer.isView(object)) {
this.encodeBinary(object);
}
else if (typeof object === "object") {
this.encodeMap(object, depth);
}
else {
// symbol, function and other special object come here unless extensionCodec handles them.
throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(object)}`);
}
}
encodeBinary(object) {
const size = object.byteLength;
if (size < 0x100) {
// bin 8
this.writeU8(0xc4);
this.writeU8(size);
}
else if (size < 0x10000) {
// bin 16
this.writeU8(0xc5);
this.writeU16(size);
}
else if (size < 0x100000000) {
// bin 32
this.writeU8(0xc6);
this.writeU32(size);
}
else {
throw new Error(`Too large binary: ${size}`);
}
const bytes = ensureUint8Array(object);
this.writeU8a(bytes);
}
encodeArray(object, depth) {
const size = object.length;
if (size < 16) {
// fixarray
this.writeU8(0x90 + size);
}
else if (size < 0x10000) {
// array 16
this.writeU8(0xdc);
this.writeU16(size);
}
else if (size < 0x100000000) {
// array 32
this.writeU8(0xdd);
this.writeU32(size);
}
else {
throw new Error(`Too large array: ${size}`);
}
for (const item of object) {
this.doEncode(item, depth + 1);
}
}
countWithoutUndefined(object, keys) {
let count = 0;
for (const key of keys) {
if (object[key] !== undefined) {
count++;
}
}
return count;
}
encodeMap(object, depth) {
const keys = Object.keys(object);
if (this.sortKeys) {
keys.sort();
}
const size = this.ignoreUndefined ? this.countWithoutUndefined(object, keys) : keys.length;
if (size < 16) {
// fixmap
this.writeU8(0x80 + size);
}
else if (size < 0x10000) {
// map 16
this.writeU8(0xde);
this.writeU16(size);
}
else if (size < 0x100000000) {
// map 32
this.writeU8(0xdf);
this.writeU32(size);
}
else {
throw new Error(`Too large map object: ${size}`);
}
for (const key of keys) {
const value = object[key];
if (!(this.ignoreUndefined && value === undefined)) {
this.encodeString(key);
this.doEncode(value, depth + 1);
}
}
}
encodeExtension(ext) {
if (typeof ext.data === "function") {
const data = ext.data(this.pos + 6);
const size = data.length;
if (size >= 0x100000000) {
throw new Error(`Too large extension object: ${size}`);
}
this.writeU8(0xc9);
this.writeU32(size);
this.writeI8(ext.type);
this.writeU8a(data);
return;
}
const size = ext.data.length;
if (size === 1) {
// fixext 1
this.writeU8(0xd4);
}
else if (size === 2) {
// fixext 2
this.writeU8(0xd5);
}
else if (size === 4) {
// fixext 4
this.writeU8(0xd6);
}
else if (size === 8) {
// fixext 8
this.writeU8(0xd7);
}
else if (size === 16) {
// fixext 16
this.writeU8(0xd8);
}
else if (size < 0x100) {
// ext 8
this.writeU8(0xc7);
this.writeU8(size);
}
else if (size < 0x10000) {
// ext 16
this.writeU8(0xc8);
this.writeU16(size);
}
else if (size < 0x100000000) {
// ext 32
this.writeU8(0xc9);
this.writeU32(size);
}
else {
throw new Error(`Too large extension object: ${size}`);
}
this.writeI8(ext.type);
this.writeU8a(ext.data);
}
writeU8(value) {
this.ensureBufferSizeToWrite(1);
this.view.setUint8(this.pos, value);
this.pos++;
}
writeU8a(values) {
const size = values.length;
this.ensureBufferSizeToWrite(size);
this.bytes.set(values, this.pos);
this.pos += size;
}
writeI8(value) {
this.ensureBufferSizeToWrite(1);
this.view.setInt8(this.pos, value);
this.pos++;
}
writeU16(value) {
this.ensureBufferSizeToWrite(2);
this.view.setUint16(this.pos, value);
this.pos += 2;
}
writeI16(value) {
this.ensureBufferSizeToWrite(2);
this.view.setInt16(this.pos, value);
this.pos += 2;
}
writeU32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setUint32(this.pos, value);
this.pos += 4;
}
writeI32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setInt32(this.pos, value);
this.pos += 4;
}
writeF32(value) {
this.ensureBufferSizeToWrite(4);
this.view.setFloat32(this.pos, value);
this.pos += 4;
}
writeF64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setFloat64(this.pos, value);
this.pos += 8;
}
writeU64(value) {
this.ensureBufferSizeToWrite(8);
setUint64(this.view, this.pos, value);
this.pos += 8;
}
writeI64(value) {
this.ensureBufferSizeToWrite(8);
setInt64(this.view, this.pos, value);
this.pos += 8;
}
writeBigUint64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setBigUint64(this.pos, value);
this.pos += 8;
}
writeBigInt64(value) {
this.ensureBufferSizeToWrite(8);
this.view.setBigInt64(this.pos, value);
this.pos += 8;
}
}
//# sourceMappingURL=Encoder.mjs.map
File diff suppressed because one or more lines are too long
+8
View File
@@ -0,0 +1,8 @@
/**
* ExtData is used to handle Extension Types that are not registered to ExtensionCodec.
*/
export declare class ExtData {
readonly type: number;
readonly data: Uint8Array | ((pos: number) => Uint8Array);
constructor(type: number, data: Uint8Array | ((pos: number) => Uint8Array));
}
+12
View File
@@ -0,0 +1,12 @@
/**
* ExtData is used to handle Extension Types that are not registered to ExtensionCodec.
*/
export class ExtData {
type;
data;
constructor(type, data) {
this.type = type;
this.data = data;
}
}
//# sourceMappingURL=ExtData.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"ExtDatamjs","sourceRoot":"","sources":["../src/ExtData.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,OAAO;IACT,IAAI,CAAS;IACb,IAAI,CAA6C;IAE1D,YAAY,IAAY,EAAE,IAAgD,EAAE;QAC1E,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CAClB;CACF"}
+24
View File
@@ -0,0 +1,24 @@
import { ExtData } from "./ExtData.ts";
export type ExtensionDecoderType<ContextType> = (data: Uint8Array, extensionType: number, context: ContextType) => unknown;
export type ExtensionEncoderType<ContextType> = (input: unknown, context: ContextType) => Uint8Array | ((dataPos: number) => Uint8Array) | null;
export type ExtensionCodecType<ContextType> = {
__brand?: ContextType;
tryToEncode(object: unknown, context: ContextType): ExtData | null;
decode(data: Uint8Array, extType: number, context: ContextType): unknown;
};
export declare class ExtensionCodec<ContextType = undefined> implements ExtensionCodecType<ContextType> {
static readonly defaultCodec: ExtensionCodecType<undefined>;
__brand?: ContextType;
private readonly builtInEncoders;
private readonly builtInDecoders;
private readonly encoders;
private readonly decoders;
constructor();
register({ type, encode, decode }: {
type: number;
encode: ExtensionEncoderType<ContextType>;
decode: ExtensionDecoderType<ContextType>;
}): void;
tryToEncode(object: unknown, context: ContextType): ExtData | null;
decode(data: Uint8Array, type: number, context: ContextType): unknown;
}
+72
View File
@@ -0,0 +1,72 @@
// ExtensionCodec to handle MessagePack extensions
import { ExtData } from "./ExtData.mjs";
import { timestampExtension } from "./timestamp.mjs";
export class ExtensionCodec {
static defaultCodec = new ExtensionCodec();
// ensures ExtensionCodecType<X> matches ExtensionCodec<X>
// this will make type errors a lot more clear
// eslint-disable-next-line @typescript-eslint/naming-convention
__brand;
// built-in extensions
builtInEncoders = [];
builtInDecoders = [];
// custom extensions
encoders = [];
decoders = [];
constructor() {
this.register(timestampExtension);
}
register({ type, encode, decode, }) {
if (type >= 0) {
// custom extensions
this.encoders[type] = encode;
this.decoders[type] = decode;
}
else {
// built-in extensions
const index = -1 - type;
this.builtInEncoders[index] = encode;
this.builtInDecoders[index] = decode;
}
}
tryToEncode(object, context) {
// built-in extensions
for (let i = 0; i < this.builtInEncoders.length; i++) {
const encodeExt = this.builtInEncoders[i];
if (encodeExt != null) {
const data = encodeExt(object, context);
if (data != null) {
const type = -1 - i;
return new ExtData(type, data);
}
}
}
// custom extensions
for (let i = 0; i < this.encoders.length; i++) {
const encodeExt = this.encoders[i];
if (encodeExt != null) {
const data = encodeExt(object, context);
if (data != null) {
const type = i;
return new ExtData(type, data);
}
}
}
if (object instanceof ExtData) {
// to keep ExtData as is
return object;
}
return null;
}
decode(data, type, context) {
const decodeExt = type < 0 ? this.builtInDecoders[-1 - type] : this.decoders[type];
if (decodeExt) {
return decodeExt(data, type, context);
}
else {
// decode() does not fail, returns ExtData instead.
return new ExtData(type, data);
}
}
}
//# sourceMappingURL=ExtensionCodec.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"ExtensionCodecmjs","sourceRoot":"","sources":["../src/ExtensionCodec.ts"],"names":[],"mappings":"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"}
+9
View File
@@ -0,0 +1,9 @@
type SplitTypes<T, U> = U extends T ? (Exclude<T, U> extends never ? T : Exclude<T, U>) : T;
export type SplitUndefined<T> = SplitTypes<T, undefined>;
export type ContextOf<ContextType> = ContextType extends undefined ? object : {
/**
* Custom user-defined data, read/writable
*/
context: ContextType;
};
export {};
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=context.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"contextmjs","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":""}
+20
View File
@@ -0,0 +1,20 @@
import type { DecoderOptions } from "./Decoder.ts";
import type { SplitUndefined } from "./context.ts";
/**
* It decodes a single MessagePack object in a buffer.
*
* This is a synchronous decoding function.
* See other variants for asynchronous decoding: {@link decodeAsync}, {@link decodeMultiStream}, or {@link decodeArrayStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export declare function decode<ContextType = undefined>(buffer: ArrayLike<number> | ArrayBufferView | ArrayBufferLike, options?: DecoderOptions<SplitUndefined<ContextType>>): unknown;
/**
* It decodes multiple MessagePack objects in a buffer.
* This is corresponding to {@link decodeMultiStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export declare function decodeMulti<ContextType = undefined>(buffer: ArrayLike<number> | BufferSource, options?: DecoderOptions<SplitUndefined<ContextType>>): Generator<unknown, void, unknown>;
+26
View File
@@ -0,0 +1,26 @@
import { Decoder } from "./Decoder.mjs";
/**
* It decodes a single MessagePack object in a buffer.
*
* This is a synchronous decoding function.
* See other variants for asynchronous decoding: {@link decodeAsync}, {@link decodeMultiStream}, or {@link decodeArrayStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export function decode(buffer, options) {
const decoder = new Decoder(options);
return decoder.decode(buffer);
}
/**
* It decodes multiple MessagePack objects in a buffer.
* This is corresponding to {@link decodeMultiStream}.
*
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export function decodeMulti(buffer, options) {
const decoder = new Decoder(options);
return decoder.decodeMulti(buffer);
}
//# sourceMappingURL=decode.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"decodemjs","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CACpB,MAA6D,EAC7D,OAAqD,EAC5C;IACT,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAAA,CAC/B;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,MAAwC,EACxC,OAAqD,EAClB;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AAAA,CACpC"}
+18
View File
@@ -0,0 +1,18 @@
import type { DecoderOptions } from "./Decoder.ts";
import type { ReadableStreamLike } from "./utils/stream.ts";
import type { SplitUndefined } from "./context.ts";
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export declare function decodeAsync<ContextType = undefined>(streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions<SplitUndefined<ContextType>>): Promise<unknown>;
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export declare function decodeArrayStream<ContextType>(streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions<SplitUndefined<ContextType>>): AsyncGenerator<unknown, void, unknown>;
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export declare function decodeMultiStream<ContextType>(streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecoderOptions<SplitUndefined<ContextType>>): AsyncGenerator<unknown, void, unknown>;
+30
View File
@@ -0,0 +1,30 @@
import { Decoder } from "./Decoder.mjs";
import { ensureAsyncIterable } from "./utils/stream.mjs";
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export async function decodeAsync(streamLike, options) {
const stream = ensureAsyncIterable(streamLike);
const decoder = new Decoder(options);
return decoder.decodeAsync(stream);
}
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export function decodeArrayStream(streamLike, options) {
const stream = ensureAsyncIterable(streamLike);
const decoder = new Decoder(options);
return decoder.decodeArrayStream(stream);
}
/**
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
* @throws {@link DecodeError} if the buffer contains invalid data.
*/
export function decodeMultiStream(streamLike, options) {
const stream = ensureAsyncIterable(streamLike);
const decoder = new Decoder(options);
return decoder.decodeStream(stream);
}
//# sourceMappingURL=decodeAsync.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"decodeAsyncmjs","sourceRoot":"","sources":["../src/decodeAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAKxD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,UAAgE,EAChE,OAAqD,EACnC;IAClB,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AAAA,CACpC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAgE,EAChE,OAAqD,EACb;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAAA,CAC1C;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAgE,EAChE,OAAqD,EACb;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,CACrC"}
+9
View File
@@ -0,0 +1,9 @@
import type { EncoderOptions } from "./Encoder.ts";
import type { SplitUndefined } from "./context.ts";
/**
* It encodes `value` in the MessagePack format and
* returns a byte buffer.
*
* The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`.
*/
export declare function encode<ContextType = undefined>(value: unknown, options?: EncoderOptions<SplitUndefined<ContextType>>): Uint8Array<ArrayBuffer>;
+12
View File
@@ -0,0 +1,12 @@
import { Encoder } from "./Encoder.mjs";
/**
* It encodes `value` in the MessagePack format and
* returns a byte buffer.
*
* The returned buffer is a slice of a larger `ArrayBuffer`, so you have to use its `#byteOffset` and `#byteLength` in order to convert it to another typed arrays including NodeJS `Buffer`.
*/
export function encode(value, options) {
const encoder = new Encoder(options);
return encoder.encodeSharedRef(value);
}
//# sourceMappingURL=encode.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"encodemjs","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CACpB,KAAc,EACd,OAAqD,EAC5B;IACzB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;AAAA,CACvC"}
+24
View File
@@ -0,0 +1,24 @@
import { encode } from "./encode.ts";
export { encode };
import { decode, decodeMulti } from "./decode.ts";
export { decode, decodeMulti };
import { decodeAsync, decodeArrayStream, decodeMultiStream } from "./decodeAsync.ts";
export { decodeAsync, decodeArrayStream, decodeMultiStream };
import { Decoder } from "./Decoder.ts";
export { Decoder };
import type { DecoderOptions } from "./Decoder.ts";
export type { DecoderOptions };
import { DecodeError } from "./DecodeError.ts";
export { DecodeError };
import { Encoder } from "./Encoder.ts";
export { Encoder };
import type { EncoderOptions } from "./Encoder.ts";
export type { EncoderOptions };
import { ExtensionCodec } from "./ExtensionCodec.ts";
export { ExtensionCodec };
import type { ExtensionCodecType, ExtensionDecoderType, ExtensionEncoderType } from "./ExtensionCodec.ts";
export type { ExtensionCodecType, ExtensionDecoderType, ExtensionEncoderType };
import { ExtData } from "./ExtData.ts";
export { ExtData };
import { EXT_TIMESTAMP, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, decodeTimestampToTimeSpec, encodeTimestampExtension, decodeTimestampExtension } from "./timestamp.ts";
export { EXT_TIMESTAMP, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, decodeTimestampToTimeSpec, encodeTimestampExtension, decodeTimestampExtension, };
+21
View File
@@ -0,0 +1,21 @@
// Main Functions:
import { encode } from "./encode.mjs";
export { encode };
import { decode, decodeMulti } from "./decode.mjs";
export { decode, decodeMulti };
import { decodeAsync, decodeArrayStream, decodeMultiStream } from "./decodeAsync.mjs";
export { decodeAsync, decodeArrayStream, decodeMultiStream };
import { Decoder } from "./Decoder.mjs";
export { Decoder };
import { DecodeError } from "./DecodeError.mjs";
export { DecodeError };
import { Encoder } from "./Encoder.mjs";
export { Encoder };
// Utilities for Extension Types:
import { ExtensionCodec } from "./ExtensionCodec.mjs";
export { ExtensionCodec };
import { ExtData } from "./ExtData.mjs";
export { ExtData };
import { EXT_TIMESTAMP, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, decodeTimestampToTimeSpec, encodeTimestampExtension, decodeTimestampExtension, } from "./timestamp.mjs";
export { EXT_TIMESTAMP, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, decodeTimestampToTimeSpec, encodeTimestampExtension, decodeTimestampExtension, };
//# sourceMappingURL=index.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"indexmjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,CAAC;AAInB,iCAAiC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,GACzB,CAAC"}
+15
View File
@@ -0,0 +1,15 @@
export declare const EXT_TIMESTAMP = -1;
export type TimeSpec = {
sec: number;
nsec: number;
};
export declare function encodeTimeSpecToTimestamp({ sec, nsec }: TimeSpec): Uint8Array;
export declare function encodeDateToTimeSpec(date: Date): TimeSpec;
export declare function encodeTimestampExtension(object: unknown): Uint8Array | null;
export declare function decodeTimestampToTimeSpec(data: Uint8Array): TimeSpec;
export declare function decodeTimestampExtension(data: Uint8Array): Date;
export declare const timestampExtension: {
type: number;
encode: typeof encodeTimestampExtension;
decode: typeof decodeTimestampExtension;
};
+96
View File
@@ -0,0 +1,96 @@
// https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type
import { DecodeError } from "./DecodeError.mjs";
import { getInt64, setInt64 } from "./utils/int.mjs";
export const EXT_TIMESTAMP = -1;
const TIMESTAMP32_MAX_SEC = 0x100000000 - 1; // 32-bit unsigned int
const TIMESTAMP64_MAX_SEC = 0x400000000 - 1; // 34-bit unsigned int
export function encodeTimeSpecToTimestamp({ sec, nsec }) {
if (sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC) {
// Here sec >= 0 && nsec >= 0
if (nsec === 0 && sec <= TIMESTAMP32_MAX_SEC) {
// timestamp 32 = { sec32 (unsigned) }
const rv = new Uint8Array(4);
const view = new DataView(rv.buffer);
view.setUint32(0, sec);
return rv;
}
else {
// timestamp 64 = { nsec30 (unsigned), sec34 (unsigned) }
const secHigh = sec / 0x100000000;
const secLow = sec & 0xffffffff;
const rv = new Uint8Array(8);
const view = new DataView(rv.buffer);
// nsec30 | secHigh2
view.setUint32(0, (nsec << 2) | (secHigh & 0x3));
// secLow32
view.setUint32(4, secLow);
return rv;
}
}
else {
// timestamp 96 = { nsec32 (unsigned), sec64 (signed) }
const rv = new Uint8Array(12);
const view = new DataView(rv.buffer);
view.setUint32(0, nsec);
setInt64(view, 4, sec);
return rv;
}
}
export function encodeDateToTimeSpec(date) {
const msec = date.getTime();
const sec = Math.floor(msec / 1e3);
const nsec = (msec - sec * 1e3) * 1e6;
// Normalizes { sec, nsec } to ensure nsec is unsigned.
const nsecInSec = Math.floor(nsec / 1e9);
return {
sec: sec + nsecInSec,
nsec: nsec - nsecInSec * 1e9,
};
}
export function encodeTimestampExtension(object) {
if (object instanceof Date) {
const timeSpec = encodeDateToTimeSpec(object);
return encodeTimeSpecToTimestamp(timeSpec);
}
else {
return null;
}
}
export function decodeTimestampToTimeSpec(data) {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
// data may be 32, 64, or 96 bits
switch (data.byteLength) {
case 4: {
// timestamp 32 = { sec32 }
const sec = view.getUint32(0);
const nsec = 0;
return { sec, nsec };
}
case 8: {
// timestamp 64 = { nsec30, sec34 }
const nsec30AndSecHigh2 = view.getUint32(0);
const secLow32 = view.getUint32(4);
const sec = (nsec30AndSecHigh2 & 0x3) * 0x100000000 + secLow32;
const nsec = nsec30AndSecHigh2 >>> 2;
return { sec, nsec };
}
case 12: {
// timestamp 96 = { nsec32 (unsigned), sec64 (signed) }
const sec = getInt64(view, 4);
const nsec = view.getUint32(0);
return { sec, nsec };
}
default:
throw new DecodeError(`Unrecognized data size for timestamp (expected 4, 8, or 12): ${data.length}`);
}
}
export function decodeTimestampExtension(data) {
const timeSpec = decodeTimestampToTimeSpec(data);
return new Date(timeSpec.sec * 1e3 + timeSpec.nsec / 1e6);
}
export const timestampExtension = {
type: EXT_TIMESTAMP,
encode: encodeTimestampExtension,
decode: decodeTimestampExtension,
};
//# sourceMappingURL=timestamp.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"timestampmjs","sourceRoot":"","sources":["../src/timestamp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
{"version":"7.0.0-dev.20251225.1","root":["../src/cachedkeydecoder.ts","../src/decodeerror.ts","../src/decoder.ts","../src/encoder.ts","../src/extdata.ts","../src/extensioncodec.ts","../src/context.ts","../src/decode.ts","../src/decodeasync.ts","../src/encode.ts","../src/index.ts","../src/timestamp.ts","../src/utils/int.ts","../src/utils/prettybyte.ts","../src/utils/stream.ts","../src/utils/typedarrays.ts","../src/utils/utf8.ts"]}
+5
View File
@@ -0,0 +1,5 @@
export declare const UINT32_MAX = 4294967295;
export declare function setUint64(view: DataView, offset: number, value: number): void;
export declare function setInt64(view: DataView, offset: number, value: number): void;
export declare function getInt64(view: DataView, offset: number): number;
export declare function getUint64(view: DataView, offset: number): number;
+27
View File
@@ -0,0 +1,27 @@
// Integer Utility
export const UINT32_MAX = 4294967295;
// DataView extension to handle int64 / uint64,
// where the actual range is 53-bits integer (a.k.a. safe integer)
export function setUint64(view, offset, value) {
const high = value / 4294967296;
const low = value; // high bits are truncated by DataView
view.setUint32(offset, high);
view.setUint32(offset + 4, low);
}
export function setInt64(view, offset, value) {
const high = Math.floor(value / 4294967296);
const low = value; // high bits are truncated by DataView
view.setUint32(offset, high);
view.setUint32(offset + 4, low);
}
export function getInt64(view, offset) {
const high = view.getInt32(offset);
const low = view.getUint32(offset + 4);
return high * 4294967296 + low;
}
export function getUint64(view, offset) {
const high = view.getUint32(offset);
const low = view.getUint32(offset + 4);
return high * 4294967296 + low;
}
//# sourceMappingURL=int.mjs.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"intmjs","sourceRoot":"","sources":["../../src/utils/int.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,UAAW,CAAC;AAEtC,+CAA+C;AAC/C,kEAAkE;AAElE,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,MAAc,EAAE,KAAa,EAAQ;IAC7E,MAAM,IAAI,GAAG,KAAK,GAAG,UAAa,CAAC;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,sCAAsC;IACzD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAAA,CACjC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAc,EAAE,MAAc,EAAE,KAAa,EAAQ;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,UAAa,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,sCAAsC;IACzD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAAA,CACjC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAc,EAAE,MAAc,EAAU;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,UAAa,GAAG,GAAG,CAAC;AAAA,CACnC;AAED,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,MAAc,EAAU;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,UAAa,GAAG,GAAG,CAAC;AAAA,CACnC"}
@@ -0,0 +1 @@
export declare function prettyByte(byte: number): string;
@@ -0,0 +1,4 @@
export function prettyByte(byte) {
return `${byte < 0 ? "-" : ""}0x${Math.abs(byte).toString(16).padStart(2, "0")}`;
}
//# sourceMappingURL=prettyByte.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"prettyBytemjs","sourceRoot":"","sources":["../../src/utils/prettyByte.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,IAAY,EAAU;IAC/C,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAAA,CAClF"}
+4
View File
@@ -0,0 +1,4 @@
export type ReadableStreamLike<T> = AsyncIterable<T> | ReadableStream<T>;
export declare function isAsyncIterable<T>(object: ReadableStreamLike<T>): object is AsyncIterable<T>;
export declare function asyncIterableFromStream<T>(stream: ReadableStream<T>): AsyncIterable<T>;
export declare function ensureAsyncIterable<T>(streamLike: ReadableStreamLike<T>): AsyncIterable<T>;
+28
View File
@@ -0,0 +1,28 @@
// utility for whatwg streams
export function isAsyncIterable(object) {
return object[Symbol.asyncIterator] != null;
}
export async function* asyncIterableFromStream(stream) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
return;
}
yield value;
}
}
finally {
reader.releaseLock();
}
}
export function ensureAsyncIterable(streamLike) {
if (isAsyncIterable(streamLike)) {
return streamLike;
}
else {
return asyncIterableFromStream(streamLike);
}
}
//# sourceMappingURL=stream.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"streammjs","sourceRoot":"","sources":["../../src/utils/stream.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAQ7B,MAAM,UAAU,eAAe,CAAI,MAA6B,EAA8B;IAC5F,OAAQ,MAAc,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC;AAAA,CACtD;AAED,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,uBAAuB,CAAI,MAAyB,EAAoB;IAC7F,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAElC,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO;YACT,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AAAA,CACF;AAED,MAAM,UAAU,mBAAmB,CAAI,UAAiC,EAAoB;IAC1F,IAAI,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,UAAU,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;AAAA,CACF"}

Some files were not shown because too many files have changed in this diff Show More