How to convert a Matrix4<f32> into a [f32; 4] using nalgebra - rust

I have a Matrix4<f32> representing a transformation. I would like to convert it to a [f32; 16] to use with wgpu.
I've not managed to find the right method (if there is one at all).

You can use as_slice() to convert it into a &[f32], and then convert that into a [f32; 16] using try_into().
Here's an example:
fn matrix_to_array(m: Matrix4<f32>) -> [f32; 16] {
m.as_slice().try_into().unwrap()
}

Related

How to convert a Rust array to pointer?

I couldn't find a simple thing on google. How to convert a simple Rust array to a pointer?
How to get pointer to [u8; 3]? I tried doing as *mut u8 but it wouldn't work.
Use as_ptr() or as_mut_ptr().
fn main() {
let a: [u8; 3] = [1, 2, 3];
println!("{:p}", a.as_ptr());
}
0x7ffc97350edd
Arrays coerce to slices, so any slice method may be called on an array.
Note that arrays in Rust are just blobs of memory. They does not point on some stored objects, like an arrays in C do, they are a sequence of objects.
If you have some data and want to get a pointer to it, you'll usually create a reference instead, since only references (and other pointers) can be cast to pointers with as:
fn main() {
let a: [u8; 3] = [1, 2, 3]; // a blob of data on the stack...
let a_ref = &a; // a shared reference to this data...
let a_ptr = a_ref as *const u8; // and a pointer, created from the reference
println!("{:p}", a_ptr);
}
Playground

How to call a function that returns a generic slice type on Rust

I'm reading the following code from here:
#[inline]
pub fn plane<T: Component>(&self, index: usize) -> &[T] {
if index >= self.planes() {
panic!("out of bounds");
}
if !<T as Component>::is_valid(self.format()) {
As you see, the plane function returns a slice of a generic type. Does that mean I need to always call this function like this: plane::<SomeType>::(my_index)?
The problem is that I don't know which type to use, it's not a type for the entire struct, just for this function and others.
For example, I saw
unsafe impl Component for [u8; 3] {
#[inline(always)]
fn is_valid(format: format::Pixel) -> bool {
format == format::Pixel::RGB24 || format == format::Pixel::BGR24
}
}
Does that mean T can be [u8; 3] and thus plane can return &[&[u8; 3]]?
So should I call self.plane::<u8>(index)? I tried that but I get wrong number of type arguments: expected 0, found 1 on u8. Also I don't think &[&[u8; 3]] is right.
Does that mean I need to always call this function like this: plane::<SomeType>(my_index)?
No, if Rust can infer SomeType, you don't have to provide it explicitly. If you're e.g. assigning the result of plane to a variable that you've given a type, you don't have to provide it in the call.
Does that mean T can be [u8; 3] and thus plane can return &[&[u8; 3]]?
If T is [u8; 3], plane returns &[[u8; 3]].

Using pointer casting to change the “type” of data in memory [duplicate]

I am reading raw data from a file and I want to convert it to an integer:
fn main() {
let buf: &[u8] = &[0, 0, 0, 1];
let num = slice_to_i8(buf);
println!("1 == {}", num);
}
pub fn slice_to_i8(buf: &[u8]) -> i32 {
unimplemented!("what should I do here?")
}
I would do a cast in C, but what do I do in Rust?
I'd suggest using the byteorder crate (which also works in a no-std environment):
use byteorder::{BigEndian, ReadBytesExt}; // 1.2.7
fn main() {
let mut buf: &[u8] = &[0, 0, 0, 1];
let num = buf.read_u32::<BigEndian>().unwrap();
assert_eq!(1, num);
}
This handles oddly-sized slices and automatically advances the buffer so you can read multiple values.
As of Rust 1.32, you can also use the from_le_bytes / from_be_bytes / from_ne_bytes inherent methods on integers:
fn main() {
let buf = [0, 0, 0, 1];
let num = u32::from_be_bytes(buf);
assert_eq!(1, num);
}
These methods only handle fixed-length arrays to avoid dealing with the error when not enough data is present. If you have a slice, you will need to convert it into an array.
See also:
How to get a slice as an array in Rust?
How to convert a slice into an array reference?
I'd like to give this answer here to commit the following additional details:
A working code snippet which converts slice to integer (two ways to do it).
A working solution in no_std environment.
To keep everything in one place for the people getting here from the search engine.
Without external crates, the following methods are suitable to convert from slices to integer even for no_std build starting from Rust 1.32:
Method 1 (try_into + from_be_bytes)
use core::convert::TryInto;
let src = [1, 2, 3, 4, 5, 6, 7];
// 0x03040506
u32::from_be_bytes(src[2..6].try_into().unwrap());
use core::conver::TryInto is for no_std build. And the way to use the standard crate is the following: use std::convert::TryInto;.
(And about endians it has been already answered, but let me keep it here in one place: from_le_bytes, from_be_bytes, and from_ne_bytes - use them depending on how integer is represented in memory).
Method 2 (clone_from_slice + from_be_bytes)
let src = [1, 2, 3, 4, 5, 6, 7];
let mut dst = [0u8; 4];
dst.clone_from_slice(&src[2..6]);
// 0x03040506
u32::from_be_bytes(dst);
Result
In both cases integer will be equal to 0x03040506.
This custom serialize_deserialize_u8_i32 library will safely convert back and forth between u8 array and i32 array i.e. the serialise function will take all of your u8 values and pack them into i32 values and the deserialise function will take this library’s custom i32 values and convert them back to the original u8 values that you started with.
This was built for a specific purpose, however it may come in handy for other uses; depending on whether you want/need a fast/custom converter like this.
https://github.com/second-state/serialize_deserialize_u8_i32
Here’s my implementation (for a different use case) that discards any additional bytes beyond 8 (and therefore doesn’t need to panic if not exact):
pub fn u64_from_slice(slice: &[u8]) -> u64 {
u64::from_ne_bytes(slice.split_at(8).0.try_into().unwrap())
}
The split_at() method returns a tuple of two slices: one from index 0 until the specified index and the other from the specified index until the end. So by using .0 to access the first member of the tuple returned by .split_at(8), it ensures that only the first 8 bytes are passed to u64::to_ne_bytes(), discarding the leftovers. Then, of course, it calls the try_into method on that .0 tuple member, and .unwrap() since split_at does all the custom panicking for you.

How to convert a boxed array into a Vec in Rust

I have a boxed array of structs and I want to consume this array and insert it into a vector.
My current approach would be to convert the array into a vector, but the corresponding library function does not seem to work the way I expected.
let foo = Box::new([1, 2, 3, 4]);
let bar = foo.into_vec();
The compiler error states
no method named into_vec found for type Box<[_; 4]> in the current scope
I've found specifications here that look like
fn into_vec(self: Box<[T]>) -> Vec<T>
Converts self into a vector without clones or allocation.
... but I am not quite sure how to apply it. Any suggestions?
I think there's more cleaner way to do it. When you initialize foo, add type to it. Playground
fn main() {
let foo: Box<[u32]> = Box::new([1, 2, 3, 4]);
let bar = foo.into_vec();
println!("{:?}", bar);
}
The documentation you link to is for slices, i.e., [T], while what you have is an array of length 4: [T; 4].
You can, however, simply convert those, since an array of length 4 kinda is a slice. This works:
let foo = Box::new([1, 2, 3, 4]);
let bar = (foo as Box<[_]>).into_vec();

Is there a good way to convert a Vec<T> to an array?

Is there a good way to convert a Vec<T> with size S to an array of type [T; S]? Specifically, I'm using a function that returns a 128-bit hash as a Vec<u8>, which will always have length 16, and I would like to deal with the hash as a [u8, 16].
Is there something built-in akin to the as_slice method which gives me what I want, or should I write my own function which allocates a fixed-size array, iterates through the vector copying each element, and returns the array?
Arrays must be completely initialized, so you quickly run into concerns about what to do when you convert a vector with too many or too few elements into an array. These examples simply panic.
As of Rust 1.51 you can parameterize over an array's length.
use std::convert::TryInto;
fn demo<T, const N: usize>(v: Vec<T>) -> [T; N] {
v.try_into()
.unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}
As of Rust 1.48, each size needs to be a specialized implementation:
use std::convert::TryInto;
fn demo<T>(v: Vec<T>) -> [T; 4] {
v.try_into()
.unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", 4, v.len()))
}
As of Rust 1.43:
use std::convert::TryInto;
fn demo<T>(v: Vec<T>) -> [T; 4] {
let boxed_slice = v.into_boxed_slice();
let boxed_array: Box<[T; 4]> = match boxed_slice.try_into() {
Ok(ba) => ba,
Err(o) => panic!("Expected a Vec of length {} but it was {}", 4, o.len()),
};
*boxed_array
}
See also:
How to get a slice as an array in Rust?
How do I get an owned value out of a `Box`?
Is it possible to control the size of an array using the type parameter of a generic?

Resources