hexout

Crates.iohexout
lib.rshexout
version0.3.0
created_at2025-10-08 10:27:51.709439+00
updated_at2025-10-15 11:17:42.884502+00
descriptionA compact and dependency-free, flexible and customizable hex dump library for Rust that provides beautiful, configurable binary data visualization.
homepage
repositoryhttps://github.com/the-eichonic/hexout
max_upload_size
id1873764
size60,533
(the-eichonic)

documentation

README

hexout

A compact and dependency-free, flexible and customizable hex dump library for Rust that provides beautiful, configurable binary data visualization.

Features

  • Arbitrary group sizes: Group bytes in any size from 1 to 16 bytes (not limited to 1, 2, 4, or 8)
  • Configurable layout: Adjust groups per line, address width, and spacing
  • Byte order support: Display data in big-endian or little-endian format
  • ASCII representation: Optional side-by-side ASCII view with printable character display
  • Flexible addressing: Show/hide offsets, align addresses to boundaries
  • Customizable formatting: Uppercase/lowercase hex, centerline separators
  • Partial data handling: Gracefully handles incomplete groups and missing data
  • Trait-based API: Convenient methods on byte slices via the HexOut trait

Installation

Add hexout to your Cargo.toml:

[dependencies]
hexout = "0.3"

Usage

Basic Example

use hexout::hex_out;

fn main() {
    let data = b"Hello, World!";
    let result = hex_out(data, &Default::default(), 0, 0, 0).unwrap();
    println!("{}", result);
}

Output:

00000000: 48 65 6c 6c 6f 2c 20 57  6f 72 6c 64 21          |Hello, W orld!   |

Using the Trait API

use hexout::HexOut;

fn main() {
    let data = vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
    let dump = data.hex_out().unwrap();
    println!("{}", dump);
}

Custom Settings

use hexout::{hex_out, HexOutSettings};

fn main() {
    let data: Vec<u8> = (0..32).collect();
    
    let settings = HexOutSettings {
        group_size: 4,           // 4 bytes per group (32-bit words)
        groups_per_line: 4,      // 4 groups per line
        big_endian: false,       // Little-endian byte order
        show_ascii: true,        // Show ASCII representation
        show_centerline: true,   // Add space in the middle
        uppercase: true,         // Uppercase hex digits
        ..Default::default()
    };
    
    let dump = hex_out(&data, &settings, 0, 0, 0).unwrap();
    println!("{}", dump);
}

Output:

00000000: 03020100 07060504  0B0A0908 0F0E0D0C |........ ........|
00000010: 13121110 17161514  1B1A1918 1F1E1D1C |........ ........|

16-bit Words (Big-Endian)

use hexout::{hex_out, HexOutSettings};

fn main() {
    let data: Vec<u8> = (0..32).collect();
    
    let settings = HexOutSettings {
        group_size: 2,           // 2 bytes per group (16-bit words)
        groups_per_line: 8,      // 8 groups per line
        big_endian: true,        // Big-endian byte order
        show_ascii: true,
        ..Default::default()
    };
    
    let dump = hex_out(&data, &settings, 0, 0, 0).unwrap();
    println!("{}", dump);
}

Output:

00000000: 0001 0203 0405 0607  0809 0a0b 0c0d 0e0f |........ ........|
00000010: 1011 1213 1415 1617  1819 1a1b 1c1d 1e1f |........ ........|

Paginated Output

use hexout::{hex_out, HexOutSettings};

fn main() {
    let data: Vec<u8> = (0..128).collect();
    
    // Display lines 2-3 (0-based indexing)
    let dump = hex_out(&data, &HexOutSettings::default(), 0, 2, 2).unwrap();
    println!("{}", dump);
}

Output:

00000020: 20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f | !"#$%&' ()*+,-./|
00000030: 30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f |01234567 89:;<=>?|

Custom Address Offsets

use hexout::{hex_out, HexOutSettings};

fn main() {
    let data = vec![0xAA; 16];
    
    let settings = HexOutSettings {
        address_width: 16,  // 64-bit addresses
        ..Default::default()
    };
    
    // Start addresses at 0x1000
    let dump = hex_out(&data, &settings, 8, 0, 0).unwrap();
    println!("{}", dump);
}

Output:

0000000000000000:                          aa aa aa aa aa aa aa aa |         ........|

Minimal Output (No Offsets or ASCII)

use hexout::{hex_out, HexOutSettings};

fn main() {
    let data = vec![0x12, 0x34, 0x56, 0x78];
    
    let settings = HexOutSettings {
        show_offset: false,
        show_ascii: false,
        show_centerline: false,
        ..Default::default()
    };
    
    let dump = hex_out(&data, &settings, 0, 0, 0).unwrap();
    println!("{}", dump);
}

Output:

12 34 56 78

Configuration Options

The HexOutSettings struct provides the following options:

Field Type Default Description
address_origin usize 0 The origin address to start from. Does not change the actual offset of the data, just the displayed address.
address_width usize 8 Width of the address field in hex characters
align_address bool true Align addresses to group boundaries
big_endian bool false Use big-endian byte order within groups
group_size usize 1 Number of bytes per group (1-16)
groups_per_line usize 16 Number of groups to display per line
invalid_data_placeholder char ? Character to use for invalid or out-of-bounds data
show_ascii bool true Show ASCII representation
show_centerline bool true Add extra space at line midpoint
show_offset bool true Show address offset at line start
strict bool false Return error on unaligned offsets
uppercase bool false Use uppercase hex digits (A-F)
hex_out_error_prefix Option<String> None Prefix for error indicators (e.g., ANSI codes)
hex_out_error_postfix Option<String> None Postfix for error indicators

Error Handling

The library returns Result<String, HexOutError> with the following error types:

  • InvalidGroupSize: Group size must be between 1 and 16
  • UnalignedOffset: In strict mode, offset must align with group size
use hexout::{hex_out, HexOutSettings, HexOutError};

fn main() {
    let data = vec![0u8; 10];
    let settings = HexOutSettings {
        group_size: 4,
        strict: true,
        ..Default::default()
    };
    
    // This will error because offset 1 doesn't align to group_size 4
    match hex_out(&data, &settings, 1, 0, 0) {
        Ok(dump) => println!("{}", dump),
        Err(HexOutError::UnalignedOffset { offset, group_size }) => {
            eprintln!("Error: offset {} not aligned to group size {}", offset, group_size);
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

Roadmap

[ ] Selectable 'ascii section' border symbols

[ ] Highlighting (address, ascii, number ranges?)

[ ] Streaming mode

Changelog

0.3.0 - Added column address header option - Added trait binding for Vec * Fixed an alignment issue when line data was too short

Commit count: 0

cargo fmt