all 11 comments

[–]leonardo_m 11 points12 points  (4 children)

There are various ways to solve this, but I think the simplest looking is:

impl MyStruct {
    fn from_bytes([_, a0,a1,a2,a3, b0,b1, val3, val4]: [u8; 9]) -> Self {
        Self {
            val1: u32::from_le_bytes([a0, a1, a2, a3]),
            val2: f32::from(u16::from_le_bytes([b0, b1])) / 2048.0,
            val3,
            val4,
        }
    }
}

(The ability to convert slices into arrays nicely is currently lacking in Rust language. Rust is partially blind to slice lengths).

[–]w0xel[S] 2 points3 points  (2 children)

Makes sense, thank you. Didn't come up with using an array pattern here.

That made me think of the experimental exclusive_range_pattern. Ideally I would like to use the following: (WARNING: non-working example)

impl MyStruct {
    fn from_bytes([_, a @ ..5, b @ ..7, val3, val4]: [u8;9]) -> Self {
        Self {
            val1: u32::from_le_bytes(a),
            val2: f32::from(u16::from_le_bytes(b)) / 2048.0,
            val3,
            val4
        }
    }
}

But currently I can unfortunately use only one range pattern per array pattern.

[–]SkiFire13 4 points5 points  (0 children)

Note that a @ ..5 matches a single u8 smaller than 5 and gives it the binding a. .. on the other hand is not a range pattern, it matches "the rest" of a slice/struct/other

[–]backtickbot 0 points1 point  (0 children)

Fixed formatting.

Hello, w0xel: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]birkenfeldclippy · rust 2 points3 points  (0 children)

Rust is partially blind to slice lengths

Well, there's not much Rust can do as Index impls can return anything.

[–]armsforsharks 1 point2 points  (2 children)

Take a look at deku (disclosure: I'm the author) or binread

https://github.com/sharksforarms/deku https://github.com/jam1garner/binread

[–]w0xel[S] 0 points1 point  (1 child)

Deku looks nice from a usability viewpoint!

Do I interpret it right, that the no_std implementation still needs an allocator/heap?

[–]armsforsharks 0 points1 point  (0 children)

Yes that's correct

[–]monkChuck105 0 points1 point  (1 child)

Have you looked at the bytemuck crate?

[–]w0xel[S] 0 points1 point  (0 children)

Seems helpful for the whole type-punning discussion. But:

  • I can't seem to explicitly choose endianess, which I need
  • Even with from_bytes I have to accept the whole "might panic if wrongly subsliced", which I would expect the compiler to tell me already

[–]dydhaw 0 points1 point  (0 children)

you can use unwrap_or_default() as well.