npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hextreme

v1.0.6

Published

Encode/decode hex and base64 at speed

Downloads

474

Readme

hextreme

Hex and base64 string encoding and decoding for Uint8Array — like native .toHex()/.fromHex() and .toBase64()/.fromBase64(), which are not yet widely supported.

Intended to be as fast as reasonably possible using only plain JavaScript. The secret ingredients are:

  • Conversion between strings and typed arrays via TextEncoder, TextDecoder
  • Multi-byte reads, writes and lookups using Uint16Array, Uint32Array
  • A little bit of loop unrolling (which can make a difference in Chrome/V8)

Comprehensive tests. No external dependencies. ESM and CJS exports, plus TypeScript types. 4KB zipped.

Performance

The following benchmarks were run on an M3 Pro MacBook Pro, using 32 MiB of random data, and taking the mean of 10 trials.

On this machine, across methods and browsers, the headlines are that we are:

  • 4 – 36x faster than a representative JS implementation: the feross/buffer shim package
  • 3 – 7x faster than Firefox's native methods (surprising — Firefox can surely improve on this)
  • 5 – 16x slower than Safari's native methods
                                   Chrome          Firefox             Safari
                            131.0.6778.86            133.0   Tech Preview 209

* Encode hex

This library                     22.59 ms         26.20 ms           44.10 ms
cf. native toHex                        -        126.20 ms: x5        5.80 ms: /8                                                          
cf. feross/buffer.toString      813.48 ms: x36   209.50 ms: x8      368.70 ms: x8

* Decode hex

This library                     60.22 ms         32.60 ms           92.40 ms
cf. native fromHex                      -        229.40 ms: x7        5.80 ms: /16
cf. feross/buffer.from          757.89 ms: x13   546.60 ms: x17    1371.60 ms: x15

* Encode base64

This library                     16.86 ms         20.90 ms           42.60 ms
cf. native toBase64                     -         84.00 ms: x4        3.60 ms: /12
cf. feross/buffer.toString      275.85 ms: x16   203.80 ms: x10     550.30 ms: x13

* Decode base64

This library                     52.02 ms         36.60 ms           23.90 ms
cf. native fromBase64                   -        123.00 ms: x3        4.60 ms: /5
cf. feross/buffer.from          200.80 ms: x4    248.10 ms: x7      281.70 ms: x12

Usage

To install:

npm install hextreme

Hex encoding

toHex(bytes: Uint8Array, { alphabet?: 'lower' | 'upper' } = {}): string

Encodes binary data to a hex string.

The alphabet option defaults to 'lower', but may alternatively be set to 'upper'.

Examples:

import { toHex } from 'hextreme';

toHex(new Uint8Array([254, 237, 250, 206]));
// 'feedface'

toHex(new Uint8Array([254, 237, 250, 206]), { alphabet: 'upper' });
// 'FEEDFACE'

Hex decoding

fromHex(hex: string, { onInvalidInput?: 'throw' | 'truncate' } = {}): Uint8Array

Decodes a hex string (upper-, lower- or mixed-case) to binary data.

The onInvalidInput option defaults to 'throw', in which case any non-hex character in the input causes an error to be thrown. This matches the behaviour of toHex() on a Uint8Array (where supported).

onInvalidInput may otherwise be set to 'truncate', in which case decoding stops at the first non-hex character pair encountered. This matches the behaviour of toString('hex') on a Node Buffer.

Examples:

import { fromHex } from 'hextreme';

fromHex('FEEDface');
// Uint8Array(4) [ 254, 237, 250, 206 ]

fromHex('FEEDfXce');
// Uncaught Error: Invalid pair in hex input at index 4

fromHex('FEEDfXce', { onInvalidInput: 'truncate' });
// Uint8Array(2) [ 254, 237 ]

Base64 encoding

toBase64(bytes: Uint8Array, { alphabet?: 'base64' | 'base64url', omitPadding?: boolean } = {}): string;

Encodes binary data to a base64 string.

The alphabet option defaults to 'base64'. It may alternatively be set to 'base64url', in which case the + and / characters are replaced with - and _.

The omitPadding option defaults to false, so that the output string is padded to a multiple of 4 characters using the = character. It can be set to true to prevent padding being applied.

Examples:

import { toBase64 } from 'hextreme';

const bytes = new Uint8Array([133, 233, 101, 163, 255, 191, 194, 138, 229, 116]);

toBase64(bytes);
// 'hello/+/worldA=='

toBase64(bytes, { alphabet: 'base64url' });
// 'hello_-_worldA=='

toBase64(bytes, { alphabet: 'base64url', omitPadding: true });
// 'hello_-_worldA'

Base64 decoding

fromBase64(base64: string, { alphabet?: 'base64' | 'base64url' | 'base64any', onInvalidInput?: 'throw' | 'skip' } = {}): Uint8Array;

Decodes a base64 string to binary data. Whitespace in the input string (spaces, tabs, \r and \n) is ignored.

The alphabet option defaults to 'base64', but may alternatively be set to 'base64url', in which case - and _ are expected instead of + and /, or 'base64any', in which case both alternatives are recognised.

The onInvalidInput option defaults to 'throw', in which case any non-base64, non-whitespace character in the input causes an error to be thrown. This matches the behaviour of toBase64() on a Uint8Array (where available).

onInvalidInput may otherwise be set to 'skip', in which case any non-base64 characters are skipped and decoding continues (apart from =, which ends decoding). This matches the behaviour of toString('base64') on a Node Buffer.

Note that decoding becomes roughly 2x slower if whitespace or invalid characters are encountered in the input string.

Examples:

import { fromBase64 } from 'hextreme';

fromBase64('hello/+/worldA==');
// Uint8Array(10) [ 133, 233, 101, 163, 255, 191, 194, 138, 229, 116 ]

fromBase64('hello/+/worldA');
// Uint8Array(10) [ 133, 233, 101, 163, 255, 191, 194, 138, 229, 116 ]

fromBase64('hello_-_worldA==', { alphabet: 'base64url' });
// Uint8Array(10) [ 133, 233, 101, 163, 255, 191, 194, 138, 229, 116 ]

fromBase64('hello_+_worldA==', { alphabet: 'base64any' });
// Uint8Array(10) [ 133, 233, 101, 163, 255, 191, 194, 138, 229, 116 ]

fromBase64('hello/:+/worldA==');
// Uncaught Error: Invalid character in base64 at index 6

fromBase64('hello/:+/worldA==', { onInvalidInput: 'skip' });
// Uint8Array(10) [ 133, 233, 101, 163, 255, 191, 194, 138, 229, 116 ]

Development

The source is in src. To build: npm run build.

To run tests: npm run test. To run a subset of tests on a big-endian platform (which has some different code paths), see big-endian/README.md.

To run benchmarks: npm run perfCli (for Node and Bun) and npm run perfBrowser.

Licence

Copyright (C) 2024 George MacKerron and released under the MIT License.