rust-bitcoin / rust-bitcoin/rust-bitcoin
More idiomatic code instead of impl_* macros
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 2.7k
- Forks
- 1k
- Avg merge
- 4d 1h
- Merged PRs (30d)
- 88
Description
I use rust-bitcoin a lot as a dependency and do need to create new wrapper types (like we did for the hash types) a lot. However, in order to implement them, I need a lot of different internal macro to be made exportable. While this is an option, there is another option, we can consider. For the boilerplate impl code rust allows to use generics instead of macros, which, I assume, is more idiomatic. So for instance, instead of using impl_index_newtype! https://github.com/rust-bitcoin/rust-bitcoin/blob/885fc39f4881f26929a0c3303cfccce9497ba1e4/src/internal_macros.rs#L175 for each type and making it exportable we can create just a single implementation which will cover all the cases, like this one:
#[derive(Clone, PartialEq, Eq)]
pub struct Wrapper<T, Z>(T, PhantomData<Z>);
impl<T, Z> From<T> for Wrapper<T, Z> {
#[inline]
fn from(x: T) -> Self { Self(x, PhantomData::default()) }
}
impl<T, U, Z> Index<Range<usize>> for Wrapper<T, Z>
where T: Index<Range<usize>, Output=[U]>
{
type Output = [U];
#[inline]
fn index(&self, index: Range<usize>) -> &[U] {
&self.0[index]
}
}
impl<T, U, Z> Index<RangeTo<usize>> for Wrapper<T, Z>
where T: Index<RangeTo<usize>, Output=[U]>
{
type Output = [U];
#[inline]
fn index(&self, index: RangeTo<usize>) -> &[U] {
&self.0[index]
}
}
impl<T, U, Z> Index<RangeFrom<usize>> for Wrapper<T, Z>
where T: Index<RangeFrom<usize>, Output=[U]>
{
type Output = [U];
#[inline]
fn index(&self, index: RangeFrom<usize>) -> &[U] {
&self.0[index]
}
}
impl<T, U, Z> Index<RangeFull> for Wrapper<T, Z>
where T: Index<RangeFull, Output=[U]>
{
type Output = [U];
#[inline]
fn index(&self, _: RangeFull) -> &[U] {
&self.0[..]
}
}
...and no macro use for each new type is required! To define a new wrapper type, like for hash type Txid, one need just to write
struct _TxidPhantom;
pub type Txid = Wrapper<sha256::Hash, _TxidPhantom>;
..and it will give the whole Txid functionality w/o calling to macro or doing impl's.
The same can be done not just for a Wrapper types, but in many other cases where we use the macros. So I do propose to write more idiomatic rust code and get rid from internal macros wherever is possible – I am ready to work on this change, since I have to do it otherwise somewhere on top of rust-bitcoin lib.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading src/internal_macros.rs, especially impl_index_newtype!, and compare its use for hash types such as Txid. Review the proposed generic Wrapper approach and identify which macro-based implementations it can replace; done means the selected boilerplate is removed consistently while preserving the existing wrapper functionality.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100