How to convert Vec <T> to Vec <U> without copying a vector?
I want to convert a Vec<T>
in Vec<U>
which T
is a primitive of any type, and U
is a new type T
: struct U(T)
.
I tried something like this:
struct Foo(u32);
fn do_something_using_foo(buffer: &mut Vec<Foo>) {}
fn main() {
let buffer: Vec<u32> = vec![0; 100];
do_something_using_foo(&mut buffer as Vec<Foo>);
}
I do not want to make a copy of the vector, I want to wrap the fields u32
in newtype Foo
.
This gives an error:
error[E0308]: mismatched types
--> main.rs:8:28
|
8 | do_something_using_foo(&mut buffer as Vec<Foo>);
| ^^^^^^^^^^^^^^^^^^^^^^^ expected mutable reference, found struct `std::vec::Vec`
|
= note: expected type `&mut std::vec::Vec<Foo>`
found type `std::vec::Vec<Foo>`
= help: try with `&mut &mut buffer as Vec<Foo>`
error: non-scalar cast: `&mut std::vec::Vec<u32>` as `std::vec::Vec<Foo>`
--> main.rs:8:28
|
8 | do_something_using_foo(&mut buffer as Vec<Foo>);
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error(s)
You cannot change the type of a value in Safe Rust. There is no guarantee that the two types will have the same size or the same semantics.
(T
→ U
), (Vec<T>
→ Vec<U>
, HashMap<K1, V1>
→ HashMap<K2, V2>
). , "" .
:
let buffer2 = buffer.into_iter().map(Foo).collect();
do_something_using_foo
, Foo
, u32
:
use std::borrow::{Borrow, BorrowMut};
#[derive(Debug, Clone)]
struct Foo(u32);
impl Borrow<u32> for Foo {
fn borrow(&self) -> &u32 {
&self.0
}
}
impl BorrowMut<u32> for Foo {
fn borrow_mut(&mut self) -> &mut u32 {
&mut self.0
}
}
fn do_something_using_foo<T>(buffer: &mut [T])
where
T: BorrowMut<u32>,
{
}
fn main() {
let mut buffer_u32 = vec![0u32; 100];
let mut buffer_foo = vec![Foo(0); 100];
do_something_using_foo(&mut buffer_u32);
do_something_using_foo(&mut buffer_foo);
}
- , .
- std::mem::transmute
, , .
With a, Vec
I would start by looking at an obsolete and remote function Vec::map_in_place
. Beware that this is a 170-line function full of unsafe code and diagrams arguing why it is really safe. It was removed from the standard library because no one wanted to support it.
See also: