Comments (8)
The reason for the NoUninit
requirement on the destination type is because of the guts of the function itself:
pub fn pod_collect_to_vec<
A: NoUninit + AnyBitPattern,
B: NoUninit + AnyBitPattern,
>(
src: &[A],
) -> Vec<B> {
let src_size = size_of_val(src);
// Note(Lokathor): dst_count is rounded up so that the dest will always be at
// least as many bytes as the src.
let dst_count = src_size / size_of::<B>()
+ if src_size % size_of::<B>() != 0 { 1 } else { 0 };
let mut dst = vec![B::zeroed(); dst_count];
let src_bytes: &[u8] = cast_slice(src);
let dst_bytes: &mut [u8] = cast_slice_mut(&mut dst[..]);
dst_bytes[..src_size].copy_from_slice(src_bytes);
dst
}
The actual copy from the Vec<A>
into the new Vec<B>
happens on two [u8]
references that are equal sized. However, we can't make both those [u8]
references if either type has uninit bytes.
If we really had to, we could use slice pointers instead of slice references, but then the function itself would have to do one or two unsafe calls. Even within bytemuck
, it's preferred when a function doesn't need to open up any unsafe of its own and we can just rely on the other traits/functions.
So, it's not a copy-paste error, but it's also not an absolute requirement of performing this operation. It's possible, in an absolute sense, to relax the restriction, but without a strong and clear motivating case i wouldn't want to relax the restriction "just to do it".
from bytemuck.
NoUninit
requirement on the destination type
I should have been more clear and repeated the title once more: my main concern is with the input/source type. After all, src
is only passed into cast_slice
which only requires NoUninit
.
but without a strong and clear motivating case i wouldn't want to relax the restriction "just to do it".
I don't want to suddenly derive bytemuck::Pod, bytemuck::Zeroable
on all my source types that are currently defined bytemuck::NoUninit
, if a simpler alternative is to just call cast_slice(src).to_vec()
. It'd be more in-line with what we are currently using for cast_slice
and cast_vec
.
The actual copy from the
Vec<A>
into the newVec<B>
happens on two[u8]
references that are equal sized. However, we can't make both those[u8]
references if either type has uninit bytes.
Still fine (and it makes sense) to keep NoUninit
, it is the AnyBitPattern
on A
/src
that is the culprit.
EDIT: Here I wonder what this additional complexity is for, over just calling .to_vec()
on the result from cast_slice(src)
?
If we really had to, we could use slice pointers instead of slice references, but then the function itself would have to do one or two unsafe calls. Even within
bytemuck
, it's preferred when a function doesn't need to open up any unsafe of its own and we can just rely on the other traits/functions.
Fwiw looks like everything compiles just fine without any changes (no unsafe
additions) beyond dropping AnyBitPattern
from A
.
from bytemuck.
Ahhhh, I understand the concern now (I think).
Opened #178, which I think fixes what you're after.
from bytemuck.
Here I wonder what this additional complexity is for, over just calling .to_vec() on the result from cast_slice(src)?
The way it's written casting both vecs to be bytes and then copying as bytes lets you go up in alignment (eg, u16 to u32) without fail.
from bytemuck.
Ahhhh, I understand the concern now (I think).
Opened #178, which I think fixes what you're after.
Yes, that's exactly it! Lots of unrelated changes though, but I found and approved what is relevant :)
The way it's written casting both vecs to be bytes and then copying as bytes lets you go up in alignment (eg, u16 to u32) without fail.
Right of course, that is what the Error
and unwrap
is for (within (try_)cast_*
). But means the to_vec()
might be more efficient when we only need to go down, from some &[T]
to a Vec<u8>
, by saving on the zero-initialization (which I hope to_vec()
does not do via MaybeUninit
... TBD).
from bytemuck.
Lots of unrelated changes though
Clippy is always coming after me with new warnings :(
But means the to_vec() might be more efficient when we only need to go down, from some &[T] to a Vec
If you statically know that the alignment won't go up then yeah just using cast_slice(data).to_vec()
will likely be more efficient.
I seem to recall that this fn was long ago suggested by someone that wanted to go up in alignment (u8 to u32, or maybe it was f32 to f32x4?)
from bytemuck.
Stricter clippy lints are nice at times (keeps getting better and more complete at pointing out code-smells in a codebase) but sometimes overly pedantic and unnecessarily blocking unrelated PRs. Fwiw uninlined_format_args
was demoted to pedantic.
Yeah we statically know alignment always goes to u8
, effectively using it as bytes_of
on a &[T]
, and then currently needing an owned Vec
but hope to relax that to a borrow at some point.
I seem to recall that this fn was long ago suggested by someone that wanted to go up in alignment (u8 to u32, or maybe it was f32 to f32x4?)
That's what I understand from reading the original issue #49 (PR #50). At first I just thought this was a neat helper but now understand its applicability more clearly. I'll use it in places where alignment requirements go up (and where we need an allocation).
from bytemuck.
Oh and @Lokathor, while I have you here there are a few questions that I don't feel like spawning new issues/discussions for (but can definitely do if desired!).
NoUninit
on nested structs with arrays
It seems I cannot derive(NoUninit)
on a struct that uses another derive(NoUninit)
struct within an array:
#[repr(C)]
#[derive(Clone, Copy, NoUninit)]
struct Foo(pub u32);
#[repr(C)]
#[derive(Clone, Copy, NoUninit)]
struct Bar {
my_foo: Foo,
my_foo_arr: [Foo; 4], // Error: doesn't implement Pod
blah: u32,
}
Is this something to do with #141?
io::Cursor
helpers etc?
For now I'm writing code along the lines of:
let mut blah = vec![Blah::zeroed(); num_blah];
stream.read_exact(bytemuck::cast_slice_mut(*mut blah))?;
(This is still better than the vec![0u8; ...]; read_exact(); from_raw_parts()
that was there previously, not caring about alignment)
from bytemuck.
Related Issues (20)
- use #[inline(always)] instead of #[inline] HOT 3
- Consider adding `doc(hidden)` to impl details? HOT 1
- Allow deriving `Zeroable` with explicitly provided bounds HOT 11
- Allow deriving `Pod` for structs where generics are used only as `PhantomData` HOT 2
- Derive macro doesn't work when exported HOT 1
- Fails to compile with rustc 1.72.0-nightly (fe7454bf4 2023-06-19) HOT 8
- Raw pointer cast functions HOT 4
- Cannot use derive macros when reexporting bytemuck from library HOT 2
- Crate makes assumptions about bool values HOT 5
- Safe `offset_of` for packed structs using `addr_of`? HOT 9
- `ASSERT_SIZE_MULTIPLE_OF` when casting `&[u8]` to `&[[u8; 16]]` HOT 1
- Crate documentation is misleading, implies `Pod` required for all functions. HOT 3
- the `FooBits` type generated by `#[derive(CheckedBitPattern)]` should implement `NoUninit` if `Self` is `NoUninit` HOT 3
- False positive derive error for `TransparentWrapper` around types like `Box` HOT 1
- Potential rustc bug related to deriving ByteEq HOT 2
- no-uninit trait with interior mutability HOT 6
- Deriving Pod for arbitrary generic types HOT 1
- Why use from_bytes when you can use pod_read_unaligned? HOT 5
- Build error on nightly-2024-02-05 HOT 1
- Bytemuck 1.14.2 does not build on stable HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bytemuck.