Skip to content

Introduce Char enum and rewrite BytesToHexIter to return it#236

Merged
apoelstra merged 3 commits intorust-bitcoin:masterfrom
mpbagot:feature/iter-char-pair
Apr 19, 2026
Merged

Introduce Char enum and rewrite BytesToHexIter to return it#236
apoelstra merged 3 commits intorust-bitcoin:masterfrom
mpbagot:feature/iter-char-pair

Conversation

@mpbagot
Copy link
Copy Markdown
Contributor

@mpbagot mpbagot commented Apr 17, 2026

Currently, BytesToHexIter takes in u8 and returns char. By introducting an enum Char type, we can use that in place of char to improve type safety. Further, by returning pairs of Chars, we can eliminate bugs associated with the internal buffer and allow users to trivially control character/nibble order during encoding.

  • Patch 1 introduces the Char enum and replaces u8 in Table with it
  • Patch 2 rewrites BytesToHexIter to return [Char; 2], including updating the benchmarks to suit.
  • Patch 3 updates the api files.

Closes #234

@mpbagot
Copy link
Copy Markdown
Contributor Author

mpbagot commented Apr 17, 2026

It should be noted that I didn't introduce any of these traits for Char that Kix suggested (only From for char and u8):

// These are trivially correct `unsafe` casts
impl AsRef<str> for [Char] { /* ... */ }
impl<const N: usize> AsRef<str> for [Char; N] { /* ... */ }
impl AsRef<[u8]> for [Char] { /* ... */ }
impl<const N: usize> AsRef<[u8]> for [Char; N] { /* ... */ }
impl<const N: usize> AsRef<[u8; N]> for [Char; N] { /* ... */ }
// Borrows and mutable casts just as AsRef
impl<const N: usize> From<[Char; N]> for [u8; N] { /* ... */ }

These seem to have problems with orphan rules, since [Char; N] is considered a foreign type. Happy to look again if I've missed something obvious or if someone would like to do a follow-up for them.

@apoelstra
Copy link
Copy Markdown
Member

Frustrating. I think you're correct about the orphan rules.

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK aef87f4; successfully ran local tests

Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK aef87f4

@tcharding
Copy link
Copy Markdown
Member

tcharding commented Apr 18, 2026

since [Char; N] is considered a foreign type

We could add a Pair type which would solve this problem and eliminate having to think which array index is the high nibble and which is the low?

@apoelstra
Copy link
Copy Markdown
Member

We could add a Pair type which would solve this problem and eliminate having to think which array index is the high nibble and which is the low?

IMO this is too much abstraction. It will be harder for users to fight their way out of our types to get real data than it would be for them to just have to manually pull apart arrays.

I also think it's "obvious" that the first nybble is the high one and the second one is the low one. I don't think I've ever seen a byte vector hex-encoded any other way.

@apoelstra
Copy link
Copy Markdown
Member

aef87f4 needs rebase

@tcharding
Copy link
Copy Markdown
Member

Works for me!

mpbagot added 3 commits April 18, 2026 13:04
The set of valid hex characters is highly limited and can easily be
encoded into an enum with a u8 representation. In doing so, we can
enforce the set of characters in the encoding table by the type system,
rather than relying on u8 directly. This new Char type can also be used
as a more expressive return type in place of u8 throughout the crate.

Introduce Char enum and convert Table to be defined using it instead of
u8.
Currently, BytesToHexIter takes in u8 and returns char. As such, it
uses an internal buffer to facilitate the 1 -> 2 ratio of input to
output. With the introduction of the Char type, we can now use Char
in place of char to improve type safety. Further, by returning pairs
of Chars, we can eliminate bugs associated with the internal buffer
and allow users to trivially control nibble order during encoding.

Replace char iterator item type on BytesToHexIter with [Char; 2].
Update benchmarks as necessary.
@mpbagot mpbagot force-pushed the feature/iter-char-pair branch from aef87f4 to becc2de Compare April 18, 2026 03:07
Copy link
Copy Markdown
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK becc2de

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK becc2de; successfully ran local tests

@apoelstra apoelstra merged commit 65c508b into rust-bitcoin:master Apr 19, 2026
15 checks passed
@Kixunil Kixunil mentioned this pull request Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should BytesToHexIter be byte-level reverse, or char-level reverse?

3 participants