philiprehberger-hex
Hex encoding, decoding, and dump formatting for binary data
Requirements
- Ruby >= 3.1
Installation
Add to your Gemfile:
gem "philiprehberger-hex"
Or install directly:
gem install philiprehberger-hex
Usage
require "philiprehberger/hex"
Philiprehberger::Hex.encode('hello') # => "68656c6c6f"
Philiprehberger::Hex.decode('68656c6c6f') # => "hello"
Prefix and Uppercase
Philiprehberger::Hex.encode('hello', prefix: true) # => "0x68656c6c6f"
Philiprehberger::Hex.encode('hello', uppercase: true) # => "68656C6C6F"
Philiprehberger::Hex.encode('hello', prefix: true, uppercase: true) # => "0x68656C6C6F"
Philiprehberger::Hex.decode('0x68656c6c6f') # => "hello" (auto-strips prefix)
Hex Dump
Philiprehberger::Hex.dump("Hello, World!\n")
# 00000000: 4865 6c6c 6f2c 2057 6f72 6c64 210a Hello, World!.
Grouped Format
Philiprehberger::Hex.format('hello', group: 1) # => "68 65 6c 6c 6f"
Philiprehberger::Hex.format('hello', group: 2) # => "6865 6c6c 6f"
Validation
Philiprehberger::Hex.valid?('abcdef') # => true
Philiprehberger::Hex.valid?('xyz') # => false
Byte Array
Philiprehberger::Hex.bytes_from('48656c6c6f') # => [72, 101, 108, 108, 111]
Philiprehberger::Hex.from_bytes([72, 101, 108, 108, 111]) # => "48656c6c6f"
Normalize
Philiprehberger::Hex.normalize('0x AA:BB-CC_dd') # => "aabbccdd"
Philiprehberger::Hex.normalize('0x AA:BB-CC_dd', uppercase: true) # => "AABBCCDD"
Constant-time Comparison
# Safe for comparing MAC/HMAC/signature hex values
Philiprehberger::Hex.secure_equal?('abcd', 'ABCD') # => true
Philiprehberger::Hex.secure_equal?('aa', 'ab') # => false
Chunk
Philiprehberger::Hex.chunk('aabbccdd', size: 2) # => ["aabb", "ccdd"]
Philiprehberger::Hex.chunk('aabbccddee', size: 2) # => ["aabb", "ccdd", "ee"]
Compare
Philiprehberger::Hex.compare('aabb', 'aacc')
# => [{ offset: 1, expected: "bb", actual: "cc" }]
Bitwise Operations
Philiprehberger::Hex.xor('ff00', '0f0f') # => "f00f"
Philiprehberger::Hex.and('ff00', '0f0f') # => "0f00"
Philiprehberger::Hex.or('ff00', '0f0f') # => "ff0f"
Philiprehberger::Hex.not('ff00') # => "00ff"
Random Hex
Philiprehberger::Hex.random(16) # => "a3f2b7c891d4e5f6..." (32 hex chars)
Extract Range
Philiprehberger::Hex.extract_range('aabbccdd', offset: 1, length: 2) # => "bbcc"
Swap Endian
Philiprehberger::Hex.swap_endian('aabbccdd') # => "ddccbbaa"
Pad
Philiprehberger::Hex.pad('ff', length: 4) # => "000000ff"
Philiprehberger::Hex.pad('ff', length: 4, side: :right) # => "ff000000"
Integer Conversion
Philiprehberger::Hex.to_int('ff') # => 255
Philiprehberger::Hex.from_int(255) # => "ff"
Philiprehberger::Hex.from_int(255, bytes: 4) # => "000000ff"
API
| Method | Description |
|---|---|
Hex.encode(str, prefix:, uppercase:) |
Encode a string to hexadecimal with optional prefix and case |
Hex.decode(hex) |
Decode a hexadecimal string to binary (auto-strips 0x) |
Hex.dump(str) |
Produce an xxd-style hex dump |
Hex.format(str, group:) |
Format hex output with configurable grouping |
Hex.valid?(str) |
Check if a string is valid hexadecimal |
Hex.bytes_from(hex) |
Convert a hex string to an integer byte array |
Hex.from_bytes(bytes) |
Build a hex string from an integer byte array |
Hex.normalize(hex, uppercase:) |
Strip prefix, whitespace, and separators; return canonical hex |
Hex.secure_equal?(hex1, hex2) |
Constant-time hex comparison, safe for MAC/HMAC checks |
Hex.chunk(hex, size:) |
Split a hex string into an array of byte-aligned chunks |
Hex.compare(hex1, hex2) |
Compare two hex strings and return byte-level differences |
Hex.xor(hex1, hex2) |
XOR two hex strings and return the hex result |
Hex.and(hex1, hex2) |
Bitwise AND of two hex strings |
Hex.or(hex1, hex2) |
Bitwise OR of two hex strings |
Hex.not(hex) |
Bitwise NOT (one's complement) of a hex string |
Hex.random(n) |
Generate a random hex string of n bytes |
Hex.extract_range(hex, offset:, length:) |
Extract a range of bytes from a hex string |
Hex.swap_endian(hex) |
Reverse byte order of a hex string |
Hex.pad(hex, length:, side:) |
Pad hex string to target byte length with zeros |
Hex.to_int(hex) |
Convert a hex string to an integer |
Hex.from_int(int, bytes:) |
Convert an integer to a hex string |
Development
bundle install
bundle exec rspec
bundle exec rubocop
Support
If you find this project useful: