ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

深入解析 nushell 的 nu-pretty-hex:可定制、带颜色与 ASCII 列的 Rust 十六进制转储库

深入解析 nushell 的 nu-pretty-hex:可定制、带颜色与 ASCII 列的 Rust 十六进制转储库 深入解析 nushell 的 nu-pretty-hex可定制、带颜色与 ASCII 列的 Rust 十六进制转储库【免费下载链接】nushellA new type of shell项目地址: https://gitcode.com/GitHub_Trending/nu/nushellnu-pretty-hex是 Nushell 仓库/data/web/disk1/git_repo/GitHub_Trending/nu/nushell中维护的一个纯 Rust 十六进制转储hex dump库它是在社区库pretty-hex基础上的重新打磨版本目标是让它更漂亮。本文将以 crates/nu-pretty-hex/README.md 为主线结合 crate 源码与它在 Nushell 内部的实际调用点系统讲解三种渲染入口、HexConfig的每个配置字段、ANSI 颜色分类规则以及fmt::Display/fmt::Debug集成等进阶用法。读完后你将掌握如何把任意字节数据渲染成带地址、分组、ASCII 列、甚至带色彩的一行或多行 hex dump并理解 Nushell 命令行工具中的二进制展示为什么看起来那么整齐。一个 crate三种渲染风格nu-pretty-hex对外提供一条 API三种口味的设计全部通过 src/lib.rs 的mod pretty_hex; pub use pretty_hex::*;统一导出函数输出形态默认配置等价的可格式化调用simple_hex(source)单行、无标题、无 ASCII 列HexConfig::simple()format!({}, source.hex_dump())pretty_hex(source)多行、含标题、地址、ASCII 列HexConfig::default()format!({:?}, source.hex_dump())config_hex(source, cfg)完全按HexConfig自定义传入的cfgformat!({:?}, source.hex_conf(cfg))从 src/pretty_hex.rs 的实现可以看到三个函数最终都汇聚到同一个底层函数hex_write只是传入的配置和with_color开关不同pub fn simple_hexT: AsRef[u8](source: T) - String { let mut writer String::new(); hex_write(mut writer, source, HexConfig::simple(), None).unwrap_or(()); writer } pub fn pretty_hexT: AsRef[u8](source: T) - String { let mut writer String::new(); hex_write(mut writer, source, HexConfig::default(), Some(true)).unwrap_or(()); writer } pub fn config_hexT: AsRef[u8](source: T, cfg: HexConfig) - String { let mut writer String::new(); hex_write(mut writer, source, cfg, Some(true)).unwrap_or(()); writer }同时 crate 还提供了一批面向std::fmt::Write的写者版本适合不经过中间String、直接写入任意缓冲区的场景src/pretty_hex.rssimple_hex_write(writer, source)等价于simple_hex的写者版pretty_hex_write(writer, source)等价于pretty_hex的写者版hex_write(writer, source, cfg, with_color)一切格式化的终极底层函数with_color传Some(true)开启 ANSI 颜色Some(false)/None关闭。tests/tests.rs中的test_hex_write_with_simple_config甚至用它配合heapless::Vec验证了在不依赖alloc的嵌入式/no_std场景下也能正常工作——这是 fork 掉上游pretty-hex后新增的关键能力之一。simple_hex一行搞定小数据simple_hex渲染单行十六进制无标题、无地址、无 ASCII 列。README 给出的标准示例use nu_pretty_hex::*; let v vec![222, 173, 190, 239, 202, 254, 32, 24]; assert_eq!(simple_hex(v), format!({}, v.hex_dump())); println!({}, v.hex_dump());输出de ad be ef ca fe 20 18注意默认的 4 字节分组前 4 个字节de ad be ef之间用单空格跨组交界处第 4、第 8 字节之后用双空格分隔。这个视觉分组正是源码头文件注释里grouped in default format without header and ASCII column所说的默认格式HexConfig::default()中width为 0不换行、无地址即是该风格。pretty_hex经典的多行标准 hexdumppretty_hex使用HexConfig::default()即 16 字节一行、4 字节一组、带标题头与 ASCII 列。README 示例use nu_pretty_hex::*; let v: [u8] random::[u8;30](); assert_eq!(pretty_hex(v), format!({:?}, v.hex_dump())); println!({:?}, v.hex_dump());输出Length: 30 (0x1e) bytes 0000: 6b 4e 1a c3 af 03 d2 1e 7e 73 ba c8 bd 84 0f 83 kN......~s...... 0010: 89 d5 cf 90 23 67 4b 48 db b1 bc 35 bf ee ....#gKH...5..输出结构分四段首行是长度标题十进制 十六进制随后每一行依次是 8 位十六进制地址、按 4 字节分组排列的十六进制字节、以及对应的 ASCII 可读列。末行不足 16 字节时十六进制区以空格补齐、ASCII 列截断到实际字节数使各行的可读列仍能左右对齐。config_hex一切皆可配置当需要精确控制版面例如去掉标题、改列宽、取消分组、指定起止位置时使用config_hex配合结构体更新语法只覆盖需要的字段use nu_pretty_hex::*; let cfg HexConfig {title: false, width: 8, group: 0, ..HexConfig::default() }; let v include_bytes!(data); assert_eq!(config_hex(v, cfg), format!({:?}, v.hex_conf(cfg))); println!({:?}, v.hex_conf(cfg));输出8 字节/行、不分组、无标题头0000: 6b 4e 1a c3 af 03 d2 1e kN...... 0008: 7e 73 ba c8 bd 84 0f 83 ~s...... 0010: 89 d5 cf 90 23 67 4b 48 ....#gKH 0018: db b1 bc 35 bf ee ...5..这一示例同时演示了 trait 方法hex_conf(cfg)的用法——它和hex_dump()一样返回Hex_, T包装器见下文与 Rust 格式化体系深度集成小节两者的区别仅是携带的配置不同。HexConfig把版面的控制权交给你HexConfig是这套库的控制面板所有布局参数都集中在这里定义见 src/pretty_hex.rs配合#[derive(Clone, Copy, Debug)]可以放心复制传递。字段类型默认值作用titlebooltrue是否在首行输出数据长度标题头asciibooltrue是否在每行末尾附加 ASCII 可读列widthusize16每行显示的源字节数为 0 时表示整段不换行且不打印地址前缀对应simple风格groupusize4每多少个字节插入一个较宽的组间距双空格0 表示整行不分组chunkusize1每个词内连续堆叠的字节数用于把字节两两/四四合并如6b4e0 表示不合并address_offsetusize0地址计数的起始偏移量skipOptionusizeNone跳过源数据开头多少个字节不显示lengthOptionusizeNone只显示源数据的前多少字节None即完整长度stylesHexStylesdefault()各类字节的 ANSI 颜色/字体样式Default的实现定义在 src/pretty_hex.rs默认即 16 字节/行、4 字节/组、带标题与 ASCII 列等价于pretty_hex的输出。而HexConfig::simple()则返回title: false, ascii: false, width: 0并保留其余字段直接支撑simple_hex。字节布局的三个联动参数width、group、chunk理解版面要先弄清width、group、chunk三者如何协同它们在 hex_write 与 delimiter 中实现。核心规则width 0数据按width字节切行每行地址为行号 * width skip address_offset格式{:08x}占满 8 位十六进制width 0整段作为一行不打印地址。delimiter(i)字节i与下一个字节之间的分隔符。当chunk 0且i恰为chunk的整数倍时插入分隔——如果group 0且i同时是group * chunk的整数倍则插入 组间距即一个更宽的列间隙否则插入单个 。README 各示例中每 4 字节一组的双空格即由此而来。chunk 1把连续多个字节黏成一个字如示例examples/hex_demo.rs注释所示——chunk: 2时输出461 7272 656e 2053 ...每 2 字节拼一个 4 位十六进制字chunk: 4时输出44617272 656e2053 6368726f 65646572每 4 字节拼一个 8 位字。切片参数skip、length、address_offsetskip与length在 hex_write 中作用于源数据上先用.skip(skip).take(amount)截出真正需要渲染的子序列再进入分行循环。address_offset则只参与地址打印不改变字节内容。examples/hex_demo.rs给出一个综合用法对字符串Darren Schroeder 含多字节 emoji做切片与自定义样式let config HexConfig { title: true, ascii: true, width: 16, group: 4, chunk: 1, address_offset: 0, skip: Some(10), // 跳过前 10 个字节 // length: Some(5), // 可选只显示 5 个字节 length: Some(50), // 最多显示 50 个字节 styles: HexStyles::default(), }; println!(ConfigHex\n{}\n, config_hex(my_string, config));值得留意的是若源数据为空hex_write 会直接返回不输出任何内容而tests/tests.rs的注释用例还验证了pretty_hex(vec![])会输出Length: 0 (0x0) bytes\n这一标题行为——空数据到底该不该有标题取决于走的是哪条渲染路径。面向AsRef[u8]的泛型设计字符串与字节数组一视同仁库的所有公开函数都使用T: AsRef[u8]泛型约束意味着Vecu8、[u8]、[u8; N]、String、str、[T]当元素为u8都能直接传入。tests/tests.rs早期注释用例明确验证了以下等价关系let str string; let string: String String::from(string); let slice: [u8] [0x73, 0x74, 0x72, 0x69, 0x6e, 0x67]; assert_eq!(simple_hex(str), 73 74 72 69 6e 67); assert_eq!(simple_hex(str), simple_hex(string)); assert_eq!(simple_hex(str), simple_hex(slice));也就是说str、String与等价字节切片会产生完全一致的输出。examples/hex_demo.rs中甚至直接把一个StringUTF-8 字符串传给pretty_hex/config_hex打印时自然带上 UTF-8 的多字节字符占用——在 ASCII 列中非 ASCII 字节会根据字节类别被替换为占位符见下节。因此调试网络包、文件头、编码字节、内存布局时你几乎不需要先做类型转换。ANSI 颜色与字节分类被 Nushell 复用的好看来源让它更漂亮的核心卖点在于颜色。库在字节分类的基础上为每一类字节提供独立的Style来自 Nushell 自研的nu-ansi-term十六进制区与 ASCII 区共用同一套分类逻辑函数 categorize_byte 的判定顺序是值为0x00的 NUL 字节 →null_charis_ascii_graphic()的可打印图形字符字母、数字、标点→printableis_ascii_whitespace()的空白类0x20空格在 ASCII 列显示为真实空格\t/\n/\r等其它空白显示为_→whitespace其余 ASCII 控制字符如0x7f等→ascii_otherASCII 列中显示为•非 ASCII 0x80→non_asciiASCII 列中显示为×。HexStylessrc/pretty_hex.rs封装这五类样式其Default定义了与 Nushell 终端主题一致的配色见 src/pretty_hex.rs类别样式null_charNULColor::Fixed(242)近灰printable可打印 ASCII青色Cyan 加粗whitespace空白绿色Green 加粗ascii_other其它 ASCII/控制字符紫色Purple 加粗non_ascii非 ASCII黄色Yellow 加粗tests/tests.rs的test_hex_colors是对这一套分类的快照式验证它构造了[0,1,2,3,ba,bb,bc,空格,\t,\n,\r,[,?,0xF0,0xFE,0xFF]覆盖全部五类字节再断言完整输出。从期望串里可以看到 NUL 的00被包上38;5;242m、可打印字符61被包上1;36m青加粗、空白09/0a/0d被包上1;32m绿加粗、非 ASCII 的f0 fe ff被包上1;33m黄加粗ASCII 列则相应出现0、真实空格、_、•与×的组合。开启颜色的方式有两种一是config_hex/pretty_hex返回的字符串本身默认就带 ANSI 转义它们内部传Some(true)二是调用底层hex_write(..., Some(true))。若目标输出不支持颜色如写日志文件、做断言比较可走simple_hex_write/hex_write(..., None)或用simple_hex/simple_hex_write。另外注意标题行的颜色内容稍有不同。启用颜色时 write_title 输出的标题会在Length: N (0xN) bytes之后追加一行null_char printable whitespace ascii_other non_ascii图例各词用对应类别的样式染色方便读者即时看懂颜色约定关闭颜色时标题只有Length: N (0xN) bytes对应tests/256.txt的期望输出。这也是pretty_hex_stream在 Nushell 中渲染时的行为来源。与 Rust 格式化体系深度集成hex_dump 与 hex_conf除了自由函数库还通过PrettyHextrait 与fmt::Display/fmt::Debug打通了 Rust 原生的格式化机制这是能用{}/{:?}直接打印的关键PrettyHextraitsrc/pretty_hex.rs对一切T: AsRef[u8]自动实现hex_dump()→ 包装为使用HexConfig::default()的Hex_, Thex_conf(cfg)→ 包装为使用指定cfg的Hex_, T。包装器Hexa, Tsrc/pretty_hex.rs同时实现了两个 trait行为恰好对应两种风格fmt::Display→ 走hex_write(..., cfg.to_simple(), None)即单行 simple 风格fmt::Debug→ 走hex_write(..., cfg, None)即完整 pretty 风格。所以 README 中出现的两个assert_eq!其实是同一结果的不同写法assert_eq!(simple_hex(v), format!({}, v.hex_dump())); // Display simple assert_eq!(pretty_hex(v), format!({:?}, v.hex_dump())); // Debug pretty assert_eq!(config_hex(v, cfg), format!({:?}, v.hex_conf(cfg)));而tests/tests.rs早期注释用例进一步验证了v.hex_conf(cfg).to_string()会输出没有地址的单行十六进制format!({:?}, v.hex_conf(cfg))则输出带地址与 ASCII 的多行版本。注意调试输出在{:?}场景下默认不带颜色with_color为None如果希望终端上既有 Debug 结构又有颜色应改用显式的config_hex或pretty_hex。在 Nushell 中的真实战场终端二进制数据展示脱离 Nushell 语境去理解这个 crate 是不完整的——它的 fork 动机恰恰来自 Nushell 的实际渲染需求。在仓库中nu-pretty-hex被两类关键 UI 场景复用1. Nushell 表格命令的字节流渲染。crates/nu-command/src/viewers/table.rs 导入nu_pretty_hex::{HexConfig, HexStyles}在handle_table_command中对ByteStreamType::Binary数据走pretty_hex_stream把二进制输出为带标题与 ASCII 的 hex dump 文本流。该函数table.rs演示了本库在真实工程中的用法以cfg.width为步长增量读取字节流第一块先由write_title手动写标题此后每块调用hex_write(..., Some(use_ansi_coloring))输出一行并累加cfg.address_offset。同时它还借用hex_styles字段接入用户配置的 ANSI 主题——这正是HexStyles从pretty_hex.rs中被 Nushell 表渲染直接消费的证据。2. Nushell explore交互式探索器的二进制视图。crates/nu-explore/src/explore/views/binary/mod.rs 与 crates/nu-explore/src/explore/views/binary/binary_widget.rs 导入HexStyles与categorize_byte用同一套字节分类与配色逻辑实现二进制视图的着色。也就是说在 Nushell 终端里对二进制数据执行table或进入 explore 二进制视图时所见到的地址列、分组、ASCII 列和颜色底层都来自本 crate。若你想在 Nushell 之外快速体验其效果可参考 examples/hex_demo.rs 运行cargo run --example hex_demo --manifest-path crates/nu-pretty-hex/Cargo.toml它会依次打印 Darren Schroeder 的ConfigHex/SimpleHex/PrettyHex三种形态、0–127 号字符的完整渲染以及一串随机字节的 pretty 输出是理解各配置字段最直观的现场演示examples目录位于 crates/nu-pretty-hex/examples。从上游 pretty-hex 到 nu-pretty-hex改动要点一览README 的 Inspiration 列表与本 crate 的自我介绍点明了它的血统与差异它 fork 自 wolandr/pretty-hex设计灵感最初来自 Haskell 生态的pretty-hex目标是把原始实现打磨得更美观。从源码对比可以确认以下增强点这些均可在本仓库源码中直接核验并非上游行为面向no_std/无alloc场景库根模块不强制依赖allochex_write等写者类 API 可工作在heapless等外部缓冲区上tests/tests.rs的test_hex_write_with_simple_config专门覆盖此路径Cargo.toml以[lib] doctest false关闭文档测试并声明最小依赖内置 ANSI 配色与字节分类新增HexStyles/categorize_byte颜色取自nu-ansi-term同时服务于 Nushell 的终端主题联动流式渲染支持Nushell 的pretty_hex_stream通过write_title 分段hex_write的方式对未知长度字节流增量输出——这一用法在原始返回整串String的 API 形态上并不直接成立。作为依赖它被声明在 crates/nu-pretty-hex/Cargo.toml 中运行时仅依赖nu-ansi-term.workspace开发期示例与测试额外使用rand与heapless。应用速查三种场景的推荐 API把前面内容收敛成可直接照抄的实践模板场景一想在日志/终端快速确认一段字节内容只要单行紧凑输出use nu_pretty_hex::*; let bytes bnushell; println!({}, simple_hex(bytes)); // 6e 75 73 68 65 6c 6c场景二做文件头/网络包等二进制分析需要地址、分组、ASCII 完整呈现use nu_pretty_hex::*; let data std::fs::read(path/to/file.bin)?; println!({}, pretty_hex(data));场景三按表格宽度精确排版——每行 8 字节、去掉标题、从第 4 字节起只打 20 字节use nu_pretty_hex::*; let cfg HexConfig { title: false, width: 8, group: 2, skip: Some(4), length: Some(20), ..HexConfig::default() }; println!({}, config_hex(data, cfg));场景四嵌入format!/println!让对象的 Display 输出十六进制可读列use nu_pretty_hex::*; println!({:#?}, blob.hex_dump()); // Debug 走完整多行 pretty 风格 println!({}, blob.hex_dump()); // Display 走单行 simple 风格 println!({:?}, blob.hex_conf(my_cfg)); // 用自定义配置的 pretty 风格需要指出以上是 crate 作为库的使用方式若你身处 Nushell 脚本环境期望的其实是上节所述的table/explore 对二进制数据的自动 hex 渲染两者共享同一实现。小结与参考索引nu-pretty-hex的定位可以概括为在pretty-hex的基础上为 Nushell 生态提供了一个带颜色的、可流式的、且保持AsRef[u8]泛型便利性的十六进制渲染引擎。从simple_hex的一行速览、到pretty_hex的标准分栏、再到HexConfig逐字段掌控版面配合hex_dump()/hex_conf()与Display/Debug的双重集成这套 API 已经覆盖了从调试打印到产品级表格渲染的全部需求。想进一步阅读源码推荐按此顺序浏览文档主入口crates/nu-pretty-hex/README.md模块公开头与文档示例crates/nu-pretty-hex/src/lib.rs全部实现三个入口 HexConfig 颜色分类 格式化 traitcrates/nu-pretty-hex/src/pretty_hex.rs可运行示例crates/nu-pretty-hex/examples/hex_demo.rs集成测试颜色快照、no_std写者测试crates/nu-pretty-hex/tests/tests.rs 与期望输出 crates/nu-pretty-hex/tests/256.txtNushell 内部消费者crates/nu-command/src/viewers/table.rs、crates/nu-explore/src/explore/views/binary/binary_widget.rs。【免费下载链接】nushellA new type of shell项目地址: https://gitcode.com/GitHub_Trending/nu/nushell创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表