Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Display trait to auto-populate the toString method and description fields #551

Merged

Conversation

thunderbiscuit
Copy link
Member

@thunderbiscuit thunderbiscuit commented Jun 4, 2024

This is one of my favourite little PRs in a long time.

We cannot write an explicit toString() method on our objects because the name clashes with the toString() method on the JVM, and alternatively we cannot add a description field on objects because it clashes with the field in Swift. This means that for objects that have a requirement for this toString() method, we actually add a method called asString(). It works, but it's uglier than it needs to be and feels a little odd (why is the toString() not implemented on this type?, a developer might ask).

But as of the 0.26 release of uniffi, if you define a Display trait on a type, it will automatically use that for the toString() method in Kotlin and the description field in Swift! This means of course that we can remove the odd-looking asString() (which achieves the same thing), but also that this is can be derived automatically for us by Rust! Here's how it looks in the UDL:

[Traits=(Display)]
interface Address { }

Old printout in Kotlin:

println("Address asString: ${addressInfo.address.asString()}")
// Address asString: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

println("Address toString: ${addressInfo.address.toString()}")
// Address toString: org.bitcoindevkit.Address@ec2cc4

New printout:

// Old stuff
println("Address asString: ${addressInfo.address.asString()}")
// Address asString: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

// Better
println("Address toString: ${addressInfo.address.toString()}")
// Address toString: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

// Pure sugar!
println("Address with implicit toString: ${addressInfo.address}")
// Address with implicit toString: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

Note that the toString() method is also applied automatically in many places, removing the need to actually write it out explicitly.

In Swift it's just as good. The difference is that you would have gotten an error if you tried to use the description field before:

print("Address description: \(addressInfo.address.description)")
// error: value of type 'Address' has no member 'description'

print("Address implicit description: \(addressInfo.address)")
Address implicit description: BitcoinDevKit.Address

You now get:

// Old stuff
print("Address asString: \(addressInfo.address.asString())")
// Address asString: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

// Pretty good
print("Address description: \(addressInfo.address.description)")
Address description: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

// Awesome!
print("Address implicit description: \(addressInfo.address)")
Address implicit description: tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e

The structs currently affected (and made better by this change) are:

  • Address
  • DescriptorSecretKey
  • DescriptorPublicKey
  • Mnemonic
  • Descriptor

But I suspect there might be many more that could use a clean toString() implementation which we did not have a clean way to provide.

Changelog notice

TODO

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

Copy link
Collaborator

@reez reez left a comment

Choose a reason for hiding this comment

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

ACK 153d9d5

I love this too

@thunderbiscuit thunderbiscuit merged commit efef600 into bitcoindevkit:master Jun 10, 2024
25 checks passed
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.

2 participants