Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a slice from a single element without copying that element?

Tags:

slice

rust

I have a really big struct (on heap and on stack) that I use in a function. Most of the time, I want a simple variable of that struct, because I'm doing stuff with the big struct directly. At one point, however, I'm forced (by a function signature) to pass this struct inside of a slice.

struct VeryBig(Vec<String>, [u64; 50]);

fn takes_slice(_: &[VeryBig]) {}

fn main() {
    let foo = VeryBig(vec!["Ferris".to_string(); 100], [27; 50]);

    // Use `foo` directly a bunch of times

    takes_slice(&foo); // <-- mismatched type

    // Use `foo` directly a bunch of times
}

This obviously and understandably leads to this error:

error[E0308]: mismatched types
  --> src/main.rs:10:17
   |
10 |     takes_slice(&foo); // <-- mismatched type
   |                 ^^^^ expected slice, found struct `VeryBig`
   |
   = note: expected type `&[VeryBig]`
              found type `&VeryBig`

So I wonder: what is the best way to solve this? I could just make foo a [VeryBig; 1], but that would mean that I have to use foo[0] everywhere where I want to use the big struct directly -- annoying. Alternatively, I could put the big struct into an array temporarily, call takes_slice and move it out of the array again. But that's also not very nice.

As far as I know, &T and &[T] should have the same memory layout (the pointee, not pointer), so I would expect there to be a way to reinterpret one as the other easily, but I haven't found such a feature.

like image 211
Lukas Kalbertodt Avatar asked Apr 26 '19 07:04

Lukas Kalbertodt


People also ask

How do you initialize slice in go?

In Go language, a slice can be created and initialized using the following ways: Using slice literal: You can create a slice using the slice literal. The creation of slice literal is just like an array literal, but with one difference you are not allowed to specify the size of the slice in the square braces[].

Is golang array ordered?

Although arrays and slices in Go are both ordered sequences of elements, there are significant differences between the two. An array in Go is a data structure that consists of an ordered sequence of elements that has its capacity defined at creation time.


1 Answers

You can use slice::from_ref.

fn from_ref<T>(s: &T) -> &[T]

In your code (Playground):

use std::slice;

takes_slice(slice::from_ref(&foo));

For mutable slices, you can use slice::from_mut. Also see this question about that topic.

See How can I convert a reference to any type to a reference to an array of length 1? for arrays.

like image 110
Lukas Kalbertodt Avatar answered Sep 23 '22 08:09

Lukas Kalbertodt