Skip to content

units: Remove InputString from the public API#3848

Closed
tcharding wants to merge 2 commits intorust-bitcoin:masterfrom
tcharding:01-03-int-function
Closed

units: Remove InputString from the public API#3848
tcharding wants to merge 2 commits intorust-bitcoin:masterfrom
tcharding:01-03-int-function

Conversation

@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding commented Jan 2, 2025

Currently InputString is in the public API of units because of the trait bound on parse::int(). We can just do the monomorphisisation manually to remove it.

This patch renames int to have three different names, one for &str one for String, and one for Box<str> e.g., units::parse::int_from_str.

Close #3708

@github-actions github-actions bot added C-bitcoin PRs modifying the bitcoin crate C-units PRs modifying the units crate C-primitives labels Jan 2, 2025
@apoelstra
Copy link
Copy Markdown
Member

Needs rebase.

Also why did you convert this function to a macro?

Also, do these new methods need to be pub?

@tcharding
Copy link
Copy Markdown
Member Author

Also why did you convert this function to a macro?

Also, do these new methods need to be pub?

Answer in 2 parts:

  • I made multiple methods to remove the Into<InputString> trait bound
  • I made a private macro to be called by the new public methods because I couldn't think how to handle the T: Integer type bound without too much trickery
  • I made the methods public because they are called from other crates. I think these should however go into the new private module (Introduce private modules and infrastructure #3844) if it has legs.

Woops that's 3 parts.

@apoelstra
Copy link
Copy Markdown
Member

Needs another rebase, sorry.

Re "without too much trickery", I'll give it a shot when I do a full review.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 6, 2025

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@github-actions github-actions bot added the API break This PR requires a version bump for the next release label Jan 6, 2025
@apoelstra
Copy link
Copy Markdown
Member

Re the macro, it seems it can be replaced with the function

fn to_int<T: FromStr<Err = core::num::ParseIntError> + TryFrom<i8>>(s: &str) -> Result<T, ParseIntError> {
        s.parse().map_err(|error| {
            ParseIntError {
                input: s.into(),
                bits: u8::try_from(core::mem::size_of::<T>() * 8).expect("max is 128 bits for u128"),
                // We detect if the type is signed by checking if -1 can be represented by it
                // this way we don't have to implement special traits and optimizer will get rid of the
                // computation.
                is_signed: T::try_from(-1i8).is_ok(),
                source: error,
            }
        })
}

(though you should fix the formatting). This is just a copy/paste of your macro but with $s replaced with s.

@tcharding
Copy link
Copy Markdown
Member Author

Mad, thanks. Will re-spin.

@tcharding
Copy link
Copy Markdown
Member Author

Ah woops, my bad. The proper answer to your original question of why did I use a macro is that using a function (like you posted) introduces an allocation in the error path but the macro moves the input string if its a String or Box<str>.

@apoelstra
Copy link
Copy Markdown
Member

Then we can make s also a generic Into<String> which will then do the right thing.

@tcharding
Copy link
Copy Markdown
Member Author

We can't do that because we don't have String, that is why we are using InputString, right. But we can't use Into<InputString> either hence the macro. Its private to the file so its not too much of a bother, right?

@apoelstra
Copy link
Copy Markdown
Member

You can do it by taking S: Into<InputString> + Borrow<str>. Then $s.parse() becomes s.borrow().parse().

Having said that, ok, I'm okay with the macro since the signature of the function winds up being a real mouthful. But if we stick with it, I'd like a more explicit comment on it explaining why we're using the macro rather than a generic function. The complicated function signature at least has the benefit of demonstrating exactly what we're trying to do.

@tcharding
Copy link
Copy Markdown
Member Author

Oooo I missed that its private so fine to use Into<InputString>. I'll have another play.

Currently `InputString` is in the public API of `units` because of the
trait bound on `parse::int()`. We can just do the monomorphisisation
manually to remove it.

This patch renames `int` to have three different names, one for `&str`
one for `String`, and one for `Box<str>`.
@tcharding
Copy link
Copy Markdown
Member Author

No more macro. I totally overcomplicated this PR by failing to realize there was nothing wrong with the current code except that it was public.

@tcharding
Copy link
Copy Markdown
Member Author

I did not close, bad GitHub - no biscuit.

@tcharding
Copy link
Copy Markdown
Member Author

I clicked re-open and its not open, what is going on here?

@tcharding
Copy link
Copy Markdown
Member Author

open sesame

@tcharding
Copy link
Copy Markdown
Member Author

Will try again later. Please click re-open @apoelstra if you read this.

@apoelstra
Copy link
Copy Markdown
Member

You force-pushed while it was closed, and this perma-closes PRs because Github is idiotic.

@tcharding
Copy link
Copy Markdown
Member Author

O, TIL. Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API break This PR requires a version bump for the next release C-bitcoin PRs modifying the bitcoin crate C-primitives C-units PRs modifying the units crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

units: Remove internals::InputString from the public API

2 participants