unicode-width

Determine the displayed width of Unicode characters and strings per UAX #11

Library
Cargo
v0.2.2
308stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
51/100Fair
Development Activity44
Maintenance12
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture78
Code Quality80
Innovation85
Learning Curve90

unicode-width is a small, no_std-compatible Rust crate that computes how many terminal columns a char or str occupies when rendered, following the rules in Unicode Standard Annex #11. It is the de facto standard for column-width calculations across the Rust ecosystem, powering terminal UIs, text editors, and CLI tools that need to align or wrap text correctly.

The crate exposes two traits, UnicodeWidthChar and UnicodeWidthStr, mirroring the ergonomics of the standard library’s string methods. An optional cjk feature (enabled by default) accounts for wide East Asian characters, while the core crate remains dependency-free and works in no_std environments such as embedded targets and kernels.

What You Get

  • UnicodeWidthChar and UnicodeWidthStr traits adding .width() and .width_cjk() methods to char and str
  • Lookup tables generated directly from Unicode Character Database data for accuracy across Unicode versions
  • An optional cjk feature (on by default) for wide East Asian character handling
  • no_std support with zero required runtime dependencies, suitable for embedded and kernel contexts
  • Conformance tests validated against the official Unicode emoji-test data

Common Use Cases

  • Aligning and wrapping text correctly in terminal UI libraries and TUI frameworks
  • Computing cursor position and line-wrapping in line-editing libraries and REPLs
  • Rendering fixed-width tables and progress bars in CLI tools
  • Building syntax-aware terminal emulators that need accurate column arithmetic

Under The Hood

Architecture — The crate’s public surface in src/lib.rs is thin: two traits, UnicodeWidthChar and UnicodeWidthStr, each with width() and width_cjk() methods. Width classification is delegated to src/lookup.rs and src/width_info.rs, which hold binary-searchable tables generated ahead-of-time from Unicode Character Database property files by the scripts in scripts/; src/props.rs decodes the packed width categories those tables return into the actual column values, keeping runtime logic to a handful of table lookups with no dynamic allocation.

Tech Stack — Pure Rust, edition 2021, MSRV 1.66, and #![no_std] by design. The only [dependencies] are optional rustc-std-workspace-std/-core shims used solely when vendored into the Rust standard library itself; regular consumers pull in zero transitive dependencies. Features are limited to cjk (default-on, wide-character support) and a legacy no-op no_std flag kept for backward compatibility.

Code Qualitytests/tests.rs and src/test.rs validate width calculations against tests/emoji-test.txt, the official Unicode emoji conformance data, and benches/ tracks performance regressions. Because the width tables are machine-generated from Unicode data rather than hand-maintained, the surface area for logic bugs is small; the crate has shipped for over a decade with incremental, well-scoped changes (e.g. treating \n as width 1, supporting Grapheme_Cluster_Break=Prepend) documented in its changelog.

API Design — The two-trait design mirrors the standard library’s own string APIs (str::len()str.width()), so there is effectively zero learning curve: add the crate, import the trait, call .width(). Method names are consistent between char and str implementations, and the CJK variant follows the identical naming pattern (width vs width_cjk), minimizing surprise for new users.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search