Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accept both slice and Vec in Rust enum/struct

Tags:

slice

vector

rust

I have some code similar to this

enum Value<'a> {
    Int(i64),
    Flt(f64),
    Vec(&'a [Value<'a>]),
}

and this lets me reuse some data; however, some times I want to accept heap-allocated data, so I would need something like this

enum Value {
   Int(i64),
   Flt(f64),
   Vec(Box<Vec<Value>>),
}

but now I cannot accept slices! I know I could always have both of them in the same enum, like this

enum Value<'a> {
   Int(i64),
   Flt(f64),
   VecSlice(&'a [Value<'a>]),
   VecBox(Box<Vec<Value<'a>>>),
}

but this is very ugly.

Is there a way to have a struct or enum that accepts both slices and vectors in the same member/variant?

I know that for functions accepting &str and String we can just set the parameters to something like T: Into<String> but I have not figured out how to do something like this for vectors inside data types.

like image 398
Joan Vene Avatar asked Jan 24 '26 22:01

Joan Vene


1 Answers

What you want is Cow:

enum Value<'a> {
    Int (i64),
    Flt (f64),
    Vec (Cow<'a, [Value<'a>]>),
}

Unfortunately this doesn't work because of #38962. Until that issue is fixed, you may need to re-implement a specialized version of Cow for Value:

enum MyCow<'a> {
    Borrowed (&'a[Value<'a>]),
    Owned (Vec<Value<'a>>)
}

impl<'a> Deref for MyCow<'a> {
    type Target = [Value<'a>];
    fn deref (&self) -> &[Value<'a>] {
        use crate::MyCow::{ Borrowed, Owned };
        match *self {
            Borrowed (borrowed) => borrowed,
            Owned (ref owned) => &owned,
        }
    }
}

playground

like image 67
Jmb Avatar answered Jan 27 '26 10:01

Jmb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!