'How to return a Vec containing variables created in a function

I want to return a Vec from a method that contains the two variables created in the method.

I know the problem is that the variable created in the method will be destroyed when the method ends。What should I do if I want to return this Vec?

fn thing2vec(thing: &Thing) -> Vec<&str> {
    let offset = chrono::FixedOffset::east(8 * 3600);
    let bt = chrono::NaiveDateTime::from_timestamp(thing.begin_ts as i64, 0).add(offset);
    let et = match thing.end_ts {
        0 => {
            "-"
        }
        _ => {
            chrono::NaiveDateTime::from_timestamp(thing.end_ts as i64, 0).add(offset).to_string().as_str()
        }
    };

   vec!(&thing.id, &thing.name, &format!("{}", thing.status), &bt.to_string(), et, &thing.comment)
}

error message:

   |
21 |             chrono::NaiveDateTime::from_timestamp(thing.end_ts as i64, 0).add(offset).to_string().as_str()
   |             ------------------------------------------------------------------------------------- temporary value created here
...
25 |    vec!(&thing.id, &thing.name, &format!("{}", thing.status), &bt.to_string(), et, &thing.comment)
   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
   |
   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)


Solution 1:[1]

If you really need to keep it a Vec, the simplest answer to pick an owned type, ie. Vec<String>, and clone if you need to. Like other comments said Cow could work as well, but does add its own complications.

If it were me, this looks like a structured format so I would just turn it into a struct and return it that way:

struct NewThing<'a> {
    id: &'a str,
    name: &'a str,
    status: String,
    // ..etc.
}

Solution 2:[2]

If not converting the &strs to Strings is important for performance, you can use Cow:

fn thing2vec<'a>(thing: &'a Thing) -> Vec<Cow<'a, str>> {
    let offset = chrono::FixedOffset::east(8 * 3600);
    let bt = chrono::NaiveDateTime::from_timestamp(thing.begin_ts as i64, 0).add(offset);
    let et = match thing.end_ts {
        0 => Cow::Borrowed("-"),
        _ => Cow::Owned(
            chrono::NaiveDateTime::from_timestamp(thing.end_ts as i64, 0)
                .add(offset)
                .to_string(),
        ),
    };

    vec![
        Cow::Borrowed(&thing.id),
        Cow::Borrowed(&thing.name),
        Cow::Owned(format!("{}", thing.status)),
        Cow::Owned(bt.to_string()),
        et,
        Cow::Borrowed(&thing.comment),
    ]
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 wannabe
Solution 2