In C, a pointer describes only how to access a value. The programmer is responsible for keeping track of who owns that value, and deciding whether and how to dispose of it once it's no longer in use.
Rust, on the other hand, tracks both through the type system. A reference describes how a value is accessed; a Box (or a bare variable or field, or an Rc/Arc, or any of a number of other types) describes how it is allocated. The rules of the language are designed to ensure that you can only take a reference to a value while that value still exists, and to ensure that you can't dispose of a value (dropping it or moving it) while there are references outstanding.
The program you're trying to write defines a type Struct
, which will own a HashMap
when initially created, but which may also borrow a hashmap someone else owns. That is possible, but it's a bit clunky, and I would try to avoid that definition if possible: decide whether Struct
should always borrow a hashmap, or should always own a hashmap, and go from there, if you can.
If you must, for whatever reason, allow both owned and borrowed values, then you want the std::borrow::Cow
(short for "copy on write") type. This is an enumerated type that has two cases. Simplifying a bit, they are:
Cow::<T>::Borrowed(&T)
, representing a value borrowed from elsehwere, and
Cow::<T>::Owned(T)
, representing an owned value.
use std::borrow::Cow;
use std::collections::HashMap;
pub struct Struct<'a> {
hm: Cow<'a, HashMap<&'a str, &'a str>>
}
impl<'a> Struct<'a> {
pub fn new() -> Self {
Self {
hm: Cow::Owned(HashMap::new()),
}
}
pub fn swap(&mut self, hm: &'a HashMap<&'a str, &'a str>) {
self.hm = Cow::Borrowed(hm);
}
}
One caveat with this approach is that you will have to decide in advance what lifetime bound to pick for 'a
. In most cases the compiler can infer it for you, but you still need to ensure that the Struct
instance lives no longer than the hashmaps that might be passed to swap
do, and lifetime constraints are how Rust does that. This will, as a result, be very awkward to work with.