[SOLVED] How to transfer ownership?

This may not be the right question to ask, but I’ve been wrestling with the borrow checker for a while.

I am trying to have a struct Bridge
with a property token_manager: TokenManger
that owns a tokens: HashMap<[u8; 4], Token>.
The Token has an id: TokenId that has a bytes: [u8; 4].

The only mutable element is the HashMap, and that’s only mutable so I can add more tokens.

I create this with

// This parses a json file and returns a collection of Tokens
// Each Token has a TokenId, which includes a byte array
let tokens: Vec<Token> = manifests::tokens::load("path/to/tokens.json");

// The Token Manager just has a hashmap and some accessors, mutators, and adders
let mut token_manager = Manager::new();

for token in tokens {
    // add() simply `self.tokens.insert(&token.id.byttes, token);`
    token_manager.add(&token);
}

RfBridge {
    tokens: &tokens_manager
}

The error I’m getting is:

error[E0515]: cannot return value referencing local variable `token_manager`
  --> src/bridge.rs:42:9
   |
42 | /         RfBridge {
45 | |             tokens: &token_manager
   | |                        ------------------ `token_manager` is borrowed here
46 | |         }
   | |_________^ returns a value referencing data owned by the current function

I have edited the code to remove unnecessary parts, but am happy to share more. Any help would be greatly appreciated. Even just a point in the right direction.

As a rule, don’t put references in you types unless they are supposed to be a view into another type.

This is because references are extremely restrictive.

@KrishnaSannasi, My first draft had no references, but I got other errors. “Cannot move value”, specifically in trying to move the Token out of the Vec and into the HashMap.

Maybe that’s a better question to ask.

If I have a vector of Tokens, how can I turn that into a HashMap where the key is a property of the Token (clone is fine), and the value is a Token?

You can use iterators to do that.

// example types
struct Token { id: [u8; 4], value: TokenValue }
struct TokenValue;

fn vec_to_hash_map(v: Vec<Token>) -> HashMap<[u8; 4], TokenValue> {
    v.into_iter()
     .map(|token| (token.id, token.value))
     .collect()
}

This works because HashMap<K, V> implements FromIterator<(K, V)>, so you can make a hash map from an iterator of tuples.

Vec::into_iter comes from the IntoIterator trait

1 Like

Well, @KrishnaSannasi that just worked beautifully! I got to get rid of all those references and lifetimes, and that is so much simpler than what I was trying to do.

Thanks a lot, friend.

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.