QR-Code-generator icon indicating copy to clipboard operation
QR-Code-generator copied to clipboard

Rust working plan

Open xamgore opened this issue 7 months ago • 4 comments

I believe @nayuki did an incredible job—check it out for yourself: demo, step-by-step guide, compact segmentation page, and optimization insights.

Memento mori. Every project reaches a stage where development slows down or stops. Clearly, @nayuki has done a lot and owes nothing to anyone. It would be a shame if such valuable work were lost.

The Rust crate qrcodegen has 2´300´000 downloads overall. This crate was built with care, which is why so many people started using it. I’d like to continue developing the crate because I’m interested in the growth of the Rust ecosystem.

If a project can’t continue to evolve, it’s effectively dead. It cannot be considered the best library by definition—even if it meets all stated goals like flexibility, correctness, minimalism, and documentation. For a project to grow, development must be delegated to the motivated community members. It's essential to maintain quality without relying on manual oversight.

Here is my perspective on what can be done to improve the situation. Most of the points below I’ve already implemented in my fork and will publish later. Others will require collaboration. It's okay to disagree with what’s been written. I’m an independent person with my own ideas—concepts I’ve developed through professional experience with Rust, as well as reading the feedback from the issues and pull requests of this repository.


Ecosystem

  • Logotype a stylized postmark with a pixel crab over it? Gonna ask my friend designer to help with it
  • Make it collaborator-friendly create .gitignore, CONTRIBUTING.md files, be welcome for improvements
  • Make it user-friendly describe common scenarios and integrate with popular rust crates
  • Compare with another crates: rxing, qrcode, qr_code, etc present as a table with pros & cons
  • Probably rename the crate to qr if @jht5945 is ok with it

Functionality

  • Kanji mode ✔︎ the Japanese community will love this
  • Bit-length optimizer ✔︎ the algorithm is present at Java codebase, but not in Rust port
    #40
  • Micro QR is supported by another crate

SVG renderer ✔︎

It's good to have out-of-the-box solution.

It was removed at 5bc7bce3, so everybody now has to copy-paste the same piece of code from examples.

  • The generated SVG could be optimized as suggested by @dominikwilkowski
    #204
  • API should support streaming to a io::Writer to not store the whole string in-memory
  • It's good to have some basic customization like colors
    https://github.com/kennytm/qrcode-rust?tab=readme-ov-file#svg-generation
  • Encourage copy-pasting the code

Image renderer ✔︎

It's a common scenario to embed a base64 .png picture into web servers.

  • Integrate the image renderer made by @constantoine https://github.com/constantoine/qrcodegen-image
  • Choose your own format encoders you just need to include jpg, gif, avif features on the image crate
  • Make it optional, under a feature flag to reduce the compilation time

Quality

  • Set up rustfmt, reformat code and doc comments ✔︎ #39
  • Bring up the linters ✔︎ cargo check, clippy
  • Cover the code with unit tests Especially check the edge cases
  • Benchmarking as a ground for further optimizations with divan or criterion
  • Check against Crate API guidelines https://rust-lang.github.io/api-guidelines/about.html
  • Merge with #[no_std] code make a separate feature flag
  • Highlight panicking methods or avoid panics at all to bring trust and provide reliability
  • Compliance with ISO/IEC 18004:2024 it would be a solid argument for picking this library
  • Introduce demo generator on docs.rs version, mask and ecc could be tuned right there

If I had complete freedom, I would do the following:

  1. Extract this repository into a separate one, where @nayuki is the owner, and I’m the maintainer with full editing rights. I already have experience with this setup in the yake-rust project.
  2. Rebase the entire history to keep only the commits relevant to the Rust library.
  3. Grant me publishing rights for new versions on crates.io.

Another option is simply to fork the project—developing an independent version of the crate. But in that case, users would be negatively affected: instead of just updating the version in their Cargo.toml, they would now have to discover that a compatible fork exists.

I am open to discussion, as my intentions clearly may not match those of @nayuki. Which is totally fine.

xamgore avatar Apr 30 '25 23:04 xamgore

There are further optimizations (further than described in my PR) that can be made in the SVG renderer. If you're keen let me know and I can submit a PR. Also if I may, I'd also make sure the new lib has a more rust interface with enums and the proper sized (unsigned) integers.

Sounds exciting

dominikwilkowski avatar May 01 '25 00:05 dominikwilkowski

@dominikwilkowski nice! I've taken your code from the gist. You can find the commit here and make a PR against that repo. I will change the commit's author a bit later.


About rendering. Most of the time people just want to render a QR code somehow. They may want to do it with yew, egui, bevy, in the form of an aforementioned SVG or a raster image. There could be customizations via a Builder pattern, if someone would like to contribute. I believe it would be fine to organize a workspace project (thus qrcodegen-image, qrcodegen-svg, qrcodegen-yew crates), or do everything via features.

  • #27
  • #77
  • #113
  • #116
  • #167
  • #178

Logo drafts dropped:

Image

xamgore avatar May 01 '25 19:05 xamgore

A partial reply, as I can't address everything mentioned:

@nayuki did an incredible job / @nayuki has done a lot and owes nothing to anyone

Thank you for being the rare example who shows an understanding that there is no entitlement in open-source software.

Micro QR

I don't know of a popular scanner that supports it.

Also note that a bunch of structures are different from full QR, like having only 1 finder pattern instead of 3, different timing pattern location, not all text modes supported ( https://www.qrcode.com/en/codes/microqr.html ) - so everything needs to be special-cased. Meanwhile, full QR is relatively regular (though there are exceptions with alignment patterns and version blocks).

Merge with #[no_std] code

The no-heap-allocation version has very different data structures and logic in order to satisfy that requirement. Probably half of the code is unique, and trying to extract a generic framework that encompasses both codebases would do more harm than good to comprehension.

Highlight panicking methods or avoid panics at all

Most of the panics come from well-documented preconditions (e.g. Version::new() requires the number to in the range [1, 40]). One non-obvious failure is that the user's text doesn't fit in any QR Code, so then DataTooLong is returned as an error object.

Some panics come from pedatically careful overflow checks like: QrSegment::make_bytes(): data.len().checked_mul(8).unwrap().

API should support streaming to a io::Writer

It depends how much you care because a QR Code has an upper bound of 177×177 modules, and the worst case SVG is something around 100 KB of text. A total non-issue for desktop/phone-like computers, but potentially a problem for embedded/microcontrollers.

It's a common scenario to embed a base64 .png picture into web servers.

Note that I know how to make PNGs from scratch. A dumb, non-compressing, dependency-free writer would be like 100 lines of code ( https://www.nayuki.io/page/dumb-png-output-java ). (Otherwise, I could progressively adopt features from the full library https://www.nayuki.io/page/png-library ). However, I still consider image output to be outside the scope of this QR Code library.

Cover the code with unit tests

I'll admit that I slipped on this point, especially in https://github.com/nayuki/QR-Code-generator/issues/214 .

Benchmarking as a ground for further optimizations

Pretty sure you'll lose a lot of clarity by optimizing for speed.

Compliance with ISO/IEC 18004:2024

This has been raised in some issues in the past, and I'm not sure how to satisfy this requirement. All I can say is that I read the specification and implemented features, but don't know what qualifies as "compliance".

proper sized (unsigned) integers

I chose to implement QrCode::get_module(x: i32, y: i32) for a reason: 2D graphics take place on a virtual plane that extends out to infinity in both directions. Once you play with any kind of offset transformation, negative numbers will be important.

nayuki avatar May 02 '25 20:05 nayuki

Hi! Coming really quick to say I do agree @nayuki did an amazing job, and that [qrcodegen-image](https://github.com/constantoine/qrcodegen-image) was made because I too thought it was outside of the scope of this lib, but a feature people (I, for one) would like. You did a bang up job, and sure there hasn't been an update in recent memory, but also I haven't really had a moment where I stumbled on stuff I didn't need.

If there's a way I can give back some time and effort, or if you wish to incorporate qrcodegen-image to into qrcodegen, please let me know :)

constantoine avatar May 06 '25 14:05 constantoine