Files
conv/README.md
T

6.8 KiB

conv

conv is a small command-line tool that converts data between common binary text encodings (hex, base32, base58, base64 variants, plain string), performs letter-case conversion (upper / lower), and applies JavaScript-style URI encoding (encodeURI / decodeURI / encodeURIComponent / decodeURIComponent).

It is built with clap for argument parsing and reads from --input, --file, or stdin, writing to --output or stdout.

Install

cargo install --path .

or build and run directly:

cargo build --release
./target/release/conv --help

Usage

conv <SPEC> [--input|-i TEXT] [--file|-f PATH] [--output|-o PATH]
  • <SPEC> is from:to (e.g. hex:base64), a text operation (upper, lower, encode-uri, decode-uri, encode-uri-component, decode-uri-component), or any alias (see below).
  • Input is read from --input (inline text) if given, otherwise --file, otherwise stdin. --input takes precedence over --file.
  • Output goes to --output if given, otherwise stdout.

Supported formats

Any pair of the formats below may be combined as from:to.

Format Encodes as Decodes as
hex lowercase hex hex (case-insensitive)
HEX uppercase hex hex (case-insensitive)
base32 lowercase base32, with = padding base32 (case-insensitive, padding optional)
BASE32 uppercase base32, with = padding base32 (case-insensitive, padding optional)
base32-ne lowercase base32, no padding base32 (case-insensitive, padding optional)
BASE32-NE uppercase base32, no padding base32 (case-insensitive, padding optional)
base58 standard base58 (Bitcoin alphabet) standard base58
base64 standard base64 (+/, = padding) lenient: standard / url-safe, with or without padding
base64-uri URL-safe base64 (-_, = padding) lenient: standard / url-safe, with or without padding
base64-ne standard base64 (+/), no padding lenient: standard / url-safe, with or without padding
base64-uri-ne URL-safe base64 (-_), no padding lenient: standard / url-safe, with or without padding
str UTF-8 string UTF-8 string

Notes:

  • Input decoding is case-insensitive. The hex/HEX and base32/BASE32 distinction only affects the output letter case.
  • The -ne (no-equals) suffix means trailing = padding is omitted — this applies to output only; all base64/base32 variants accept missing padding on input.
  • The base64 family decoders are intentionally lenient: a single base64 input format accepts standard, URL-safe, padded, and unpadded forms interchangeably.

Aliases

Short aliases are accepted anywhere a format name is. The alias's letter case follows the same upper/lower output rule:

Alias Canonical
s, string str
h hex
H HEX
b32 base32
B32 BASE32
b32-ne base32-ne
B32-NE BASE32-NE
b64 base64
b64-uri base64-uri
b64-ne base64-ne
b64-uri-ne base64-uri-ne

Any name starting with b32 / B32 / b64 expands to the corresponding base32 / BASE32 / base64 form, so future base32-* / base64-* variants gain aliases automatically. (base58 has no alias.)

URI operations

Text operations are valid as <SPEC> just like upper / lower. They implement the JavaScript encodeURI / decodeURI / encodeURIComponent / decodeURIComponent semantics (ECMA-262):

Operation (SPEC) Aliases Behavior
encode-uri en-uri encodeURI — escapes non-reserved chars only
decode-uri de-uri decodeURI — leaves reserved %XX untouched
encode-uri-component en-uri-component, en-uri-com encodeURIComponent — escapes reserved too
decode-uri-component de-uri-component, de-uri-com decodeURIComponent — decodes all %XX

The "reserved" characters that encodeURI does not escape (and that decodeURI does not decode) are ; / ? : @ & = + $ , #. Malformed % sequences or non-UTF-8 decoded bytes are an error (exit 1), matching JS URIError.

Examples

# Convert hex to base64 from an inline argument
conv hex:base64 -i deadbeef
# => 3q2+7w==

# Convert a string to base64 from stdin
echo -n hello | conv str:base64
# => aGVsbG8=

# Encode with no padding
conv str:base64-uri-ne -i 'Hello, World!'
# => SGVsbG8sIFdvcmxkIQ

# Re-add padding when converting to a padded format
conv base32-ne:base32 -i nbuq
# => nbuq====

# Letter case
echo -n hello | conv upper        # => HELLO
conv lower -f notes.txt -o notes-lower.txt

# Round-trip through base58
conv str:base58 -i 'Hello, World!' | conv base58:str
# => Hello, World!

# URI encoding
conv encode-uri -i 'https://example.com/a b?q=1'
# => https://example.com/a%20b?q=1
conv encode-uri-component -i 'https://example.com/a b?q=1'
# => https%3A%2F%2Fexample.com%2Fa%20b%3Fq%3D1
conv decode-uri-component -i 'https%3A%2F%2Fexample.com'
# => https://example.com
# decodeURI leaves reserved %3A/%3F/%3D untouched:
conv decode-uri -i 'https%3A//x/path%3Fq%3D1'
# => https%3A//x/path%3Fq%3D1
# aliases
conv en-uri -i 'a b'                 # => a%20b
conv de-uri-com -i 'a%20b'           # => a b

Exit codes & errors

  • 0 — success.
  • 1 — conversion error (invalid hex / base32 / base58 / base64 input, invalid UTF-8 for str, or an invalid SPEC). The error message is written to stderr.
  • 2 — CLI usage error (missing or malformed arguments), reported by clap.

Development

Run the test suite:

cargo test

The conversion logic lives in src/lib.rs (a library target, free of any I/O or argument parsing) and is covered by the integration tests in tests/conv.rs. The binary entry point (src/main.rs) is a thin wrapper around the library.