Skip to content

Implement IntoIterator<Item=u8> for NumBytes #294

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

Closed

Conversation

Evian-Zhang
Copy link

This PR implements IntoIterator<Item = u8> for NumBytes, since the AsRef and Borrow traits for NumBytes will have trouble with lifetime as it borrows the array.

An actual usage of this trait is when I want to convert a list of integers into bytes (i.e. flatten the generated bytes array for each integer):

fn flatten_to_bytes_array<I: ToBytes>(integers: &[I]) -> Vec<u8> {
    integers
        .iter()
        .map(|integer| integer.to_ne_bytes().into_iter())
        .flatten()
        .collect()
}

However, if I replace the into_iter with as_ref(), the borrow checker will deny the compilation since the lifetime of the array generated in to_ne_bytes() cannot live long enough. The workaround here is just as_ref().to_vec(), which involves additional heap allocations.

@cuviper
Copy link
Member

cuviper commented Oct 25, 2023

Unfortunately, it's a breaking change to add new trait requirements. A 3rd-party crate could have a ToBytes or FromBytes implementation where they use a type Bytes that doesn't implement IntoIterator, or any other use of NumBytes that would now be more constrained.

Your example function could add where I::Bytes: IntoIterator<Item = u8>, but I know it's inconvenient to propagate extra bounds on associated types like that, especially because of rust-lang/rust#20671. (And BTW, flatten can handle the into_iter() call for you.)

There's also an issue that arrays didn't implement IntoIterator until Rust 1.53, so we would have to raise MSRV. That's possible, but the breaking change above is the bigger problem.

@cuviper
Copy link
Member

cuviper commented Oct 25, 2023

FWIW, since you're keeping native-endian bytes -- if you're only concerned with primitive types, your particular example could also be written with bytemuck::cast_slice.

@Evian-Zhang
Copy link
Author

Ok, I understood. Thank you for your kind explanation.

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