Hacker News new | ask | show | jobs
by jph 2041 days ago
Congratulations! The highlight for me is stable conversion from Vec to array:

  let my_arr: [u32; 3] = my_vec.try_into().expect("msg");
3 comments

Indeed, I can't wait for const generics to become available outside of std, I've been bumping into that limitation since pre-rust-1.0 days, it'll be amazing to finally be able to rewrite all that hacky code correctly.
min_const_generics is targeted for Rust 1.50 :)
For anyone who wants to learn more: https://github.com/rust-lang/rust/pull/79135
Newbie question. Why is this useful? Wouldn't slices be enough to fulfill the use-cases this would see?
Some things want an array of a specific size. If you have a function like https://doc.rust-lang.org/stable/std/primitive.u16.html#meth...

  pub const fn from_be_bytes(bytes: [u8; 2]) -> u16
you can't pass it a slice. This would let you pass a vector to this function.

Now, because this wasn't possible previously, it means many things take a slice, and then check that the length is the length they expect, because that ends up being easier for folks. Stuff like this helps it be able to be done properly.

(This specific function is one example that is done in this style, and it's a pain. I have real world code that looks like

  let foo = u16::from_be_bytes([some_slice[0], some_slice[1]]);
This gets even worse with say, u128::from_be_bytes.)
TryInto is already implemented for slices in 1.47, so `let foo = u16::from_be_bytes(some_slice.try_into().unwrap());` would work before 1.48.

This trait wasn't implemented for vectors though, so you would have to write `let foo = u16::from_be_bytes(some_vec.to_slice().try_into().unwrap());`.

With new release you can drop `to_slice()` part. Nothing earth-shattering, but makes sense.

> TryInto is already implemented for slices in 1.47, so `let foo = u16::from_be_bytes(some_slice.try_into().unwrap());` would work before 1.48.

Rustdocs say it was 1.36 even? https://doc.rust-lang.org/nightly/std/primitive.array.html#i...

Yeah, by "In 1.47" I mean that as of 1.47 it was already implemented, didn't check since which version.
Ah fun! I missed that. Time to clean up some code...
That doesn't work with non-copyable types.
steveklabnik is (of course) correct, but you also have to consider the performance cost of a dynamicaly sized slice versus a statically sized array.

A situation I've encountered several times already is implementing statically sized FIFOs. At the moment in Rust I can't implement a type "FIFO of depth N" where is a generic, static parameter. My only choices are implementing "FIFO of depth n" where n is provided dynamically at runtime (and implemented internally using something like a VecDeque) or a completely fixed depth FIFO type that I need to duplicate for every depth (FIFO32, FIFO16, FIFO10 etc...).

If you require very high performance a dynamically checked FIFO can incur a fairly large overhead when a well optimized static FIFO can implement most operations in a couple of opcodes at most.

You maybe could write something like this:

  pub struct Fifo<T: AsMut<[u8]>> {
and then back it with an array. I learned this trick from whitequark.

(Though maybe if you want something other than a slice of bytes, this gets harder... I've used this trick for ringbuffers/mmio only, personally, so YMMV.)

That being said real const generics will make this way nicer, eventually.

I wasn't aware of this trick, thank you for that. I guess if I have to implement another FIFO before const generics land I'll have an opportunity to try it out...
Hmm. Could you do this kind of code for a static allocation at compile-time too?
I believe https://github.com/rust-lang/const-eval/issues/20 is the entry point into this kind of thing. As you can see, there's a lot of discussion. If it ever lands it'll be farther out.
I don’t think so - you can only use static functions to declare static variables. But you could do it with a macro. It’s debatable whether that would be readable and predictable, though.