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

Possibility of supporting no_std? #108

Closed
mb64 opened this issue Jun 22, 2018 · 8 comments
Closed

Possibility of supporting no_std? #108

mb64 opened this issue Jun 22, 2018 · 8 comments

Comments

@mb64
Copy link
Contributor

mb64 commented Jun 22, 2018

I was wondering if it would be possible for this library to support a #![no_std] environment. Because it's mostly conversion logic, I think a lot of it could be useful in embedded situations when it's necessary to e.g. write colors to a framebuffer, or control an RGB LED, or something like that.

My specific use case is in a project I'm working on with bare-metal raspberry pi development, where you can get a 24-bit color depth framebuffer from the GPU. I would love to just use Pixel::from_raw_slice_mut as shown in the docs, but I was forced to roll my own struct Pixel(u8, u8, u8) instead.

If it's simple enough, I'd be willing to try to implement this myself with some help. (I don't know enough about colors or about the Pixel-deriving mechanism to do anything very complicated, though.)

Thanks!

@Ogeon
Copy link
Owner

Ogeon commented Jun 22, 2018 via email

@Ogeon
Copy link
Owner

Ogeon commented Jun 25, 2018

I have just pushed a 0.4 branch for non-breaking things.

@mb64
Copy link
Contributor Author

mb64 commented Jun 25, 2018

I have a mostly-working prototype branch.
It compiles both with and without the standard library, based on whether the on-by-default std feature is enabled.

  • In general, std could just be replaced by core without repercussions
  • Gradients had to be disabled without std; its backbone is Vec, and making it work without std would require probably a complete rewrite and many breaking changes.
  • There are many uses of floating point operations like powf, sin, etc. that aren't available with no_std, so I made a workaround wrapper module to num_traits::Float that has a custom-made trait under no_std that requires users to link in their own implementations

I didn't want to open a PR because it's horribly incomplete (e.g. the tests don't even work yet without std, and there's a weird thing with derived Pixel giving lots of warnings it didn't used to) and the design decisions around FP operations are really arbitrary.

I'd appreciate any comments!

@Ogeon
Copy link
Owner

Ogeon commented Jun 25, 2018

Awesome! I will take a closer look later, but it's nice to see that you have made progress! Too bad it's not as straight forward as I thought.

Gradients had to be disabled without std; its backbone is Vec, and making it work without std would require probably a complete rewrite and many breaking changes.

That was expected. I'm fine with disabling them completely for now, in no_std mode.

There are many uses of floating point operations like powf, sin, etc. that aren't available with no_std, [...]

I didn't know that... Annoying, but I see why it's necessary. I did a bit of research and it looks like there are some attempts to writing pure Rust replacements for libm. None of the alternatives I found stood out as optimal, but mish looks like it has a lot of features (although unoptimized). I'm not sure what would be the best thing to do, but it doesn't feel great to require external functions to exist.

and there's a weird thing with derived Pixel giving lots of warnings it didn't used to

That sounds weird. It didn't look like you did a lot of changes there, but maybe the generated code need to be tweaked more. Hard to say without seeing the warnings.

@mb64
Copy link
Contributor Author

mb64 commented Jun 26, 2018

Thanks for the pointer to mish! I changed it to now use functions from both mish and m.

What would be optimal would be to only have those crates as dependencies under no_std, but Cargo doesn't support that.

Is adding a dependency (even if it's not used) OK for a patch release, or is it a breaking change?

@Ogeon
Copy link
Owner

Ogeon commented Jun 26, 2018

It's not breaking if it doesn't replace a public dependency (any dependency items that are exported from this library), but I realized that we have entered breaking territory anyway. The fact that default_features = false removes a feature that was always on before is quite breaking. I do still think having an std feature is nice, so let's not worry about that and aim for version 0.5.0 instead.

As for always including them, they seem small enough to not be a burden, but it's icky. I'm also not sure m really works for f64, since a lot (all?) of those functions are unimplemented!() in the repo. It's very tempting to just copy-paste functions from here and there and keep a private math module until something proper pops up (there's also the unreleased math.rs). May be just as good/bad if none of them are maintained, accurate or performant anyway.

Yet another alternative is to hook in the libm bindings on linux, but that's a bit niche and will add C dependencies.

@mb64
Copy link
Contributor Author

mb64 commented Jun 28, 2018

Here's my idea for this, let me know what you think.

From a user's perspective:

  • If they're using the standard library, they're all set! No math dependencies are pulled in, and no Cargo features need tweaking.
  • If they're not, then they can set default-features = false. (The named-from-str requires std because of phf, anyway.) They also have to deal with floating point operations, however:
    • Either enable the soft-float feature, pulling in math libraries;
    • Or supply them themselves with extern "C" declarations. This is useful if their platform has hard-float capabilities and they want to write a (presumably faster) asm!() implementation or something.

Some more notes about this: It should be noted that the soft-float feature is a best-effort implementation, not guarunteeing exactness (there are disclaimers to this effect in most of the math libraries out there). I also think that supplying floating-point routines via extern "C" might benefit from being semver-exempt, in case new math is necessary in a point releease.

@Ogeon
Copy link
Owner

Ogeon commented Jun 28, 2018

That sounds like a good plan to get it all going! It can always be improved if a better option appears. It would be nice if you could add a section in the readme that explains why it's not trivial and give an example or at least some pointers to how to get it working without soft-float. I guess that would also match your own use case, right?

@mb64 mb64 mentioned this issue Jul 9, 2018
@Ogeon Ogeon added this to the 0.5.0 milestone Jul 10, 2018
bors bot added a commit that referenced this issue Aug 28, 2018
110: No std support r=Ogeon a=mb64

Adds support for using palette without the standard library, as discussed in issue #108.

Fixes #108.

One tiny question: because this would be in a future release (not 0.4.0), what version should be in the README example Cargo.toml for `#![no_std]`?  I put 0.4, but was unsure about if it should be something different.

Co-authored-by: Mark Barbone <mark.l.barbone@gmail.com>
@bors bors bot closed this as completed in #110 Aug 28, 2018
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

No branches or pull requests

2 participants