How to convert Vec <T> to Vec <U> without copying a vector?

I want to convert a Vec<T>in Vec<U>which Tis a primitive of any type, and Uis 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 u32in 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)
+4
source share
1 answer

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.

(TU), (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, VecI 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:

+8
source

Source: https://habr.com/ru/post/1692321/


All Articles