I have the following code in Python for which I am attempting to write a Rust equivalent:
from dataclasses import dataclass
from typing import Dict, List, Union
import unittest
@dataclass
class Node:
children: Dict[str, Union['Node', str]]
def get_parent_with_prefix(name_path: List[str], root: Node) -> Node:
"""Returns the node whose root-to-parent-node keys match the longest prefix in name_path.
Removes the common prefix from name_path."""
if name_path:
name_path_first = name_path[0]
if name_path_first in root.children:
parent = root.children[name_path_first]
if isinstance(parent, Node):
del name_path[0]
if name_path:
return get_parent_with_prefix(name_path, parent)
return root
class TestNode(unittest.TestCase):
def helper(self, node: Node, name_path: List[str], name_path_expect: List[str], node_expect: Node):
self.assertEqual(node_expect, get_parent_with_prefix(name_path, node))
self.assertEqual(name_path_expect, name_path)
def test_get_parent_with_prefix(self):
node_b = Node({'c': Node({}), 'd': 'X'})
node_a = Node({'b': node_b})
root = Node({'a': node_a})
self.helper(root, ['a'], [], root)
self.helper(root, ['a', 'b'], [], node_a)
self.helper(root, ['a', 'b', '1'], ['1'], node_b)
self.helper(root, ['a', 'b', 'c'], [], node_b)
self.helper(root, ['a', 'b', 'd'], ['d'], node_b)
self.helper(root, ['b'], ['b'], root)
In Rust, I have so far (the return type needs to be mutable):
use std::collections::HashMap;
#[derive(Debug, Eq, PartialEq)]
pub enum NodeVal {
A(Node),
B(String),
}
#[derive(Debug, Default, Eq, PartialEq)]
pub struct Node {
pub children: HashMap<String, NodeVal>,
}
fn get_parent_with_prefix<'a>(name_path: &mut Vec<String>, root: &'a mut Node) -> &'a mut Node {
match name_path.first() {
Some(name_path_first) => match root.children.get_mut(name_path_first) {
Some(NodeVal::A(parent)) => {
name_path.remove(0);
if name_path.is_empty() {
root
} else {
get_parent_with_prefix(name_path, parent)
}
}
_ => root,
},
_ => root,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn helper(
node: &mut Node,
name_path: &mut Vec<String>,
name_path_expect: &mut Vec<String>,
node_expect: &mut Node,
) {
assert_eq!(node_expect, get_parent_with_prefix(name_path, node));
assert_eq!(name_path_expect, name_path);
}
#[test]
fn test_get_parent_with_prefix() {
let mut node_b = Node {
children: HashMap::from([
("c".to_string(), NodeVal::A(Node::default())),
("d".to_string(), NodeVal::B("X".to_string())),
]),
};
let mut node_a = Node {
children: HashMap::from([("b".to_string(), NodeVal::A(node_b))]),
};
let mut root = Node {
children: HashMap::from([("a".to_string(), NodeVal::A(node_a))]),
};
helper(
&mut root,
&mut vec!["a".to_string()],
&mut Vec::new(),
&mut root,
);
helper(
&mut root,
&mut vec!["a".to_string(), "b".to_string()],
&mut Vec::new(),
&mut node_a,
);
helper(
&mut root,
&mut vec!["a".to_string(), "b".to_string(), "1".to_string()],
&mut vec!["1".to_string()],
&mut node_b,
);
helper(
&mut root,
&mut vec!["a".to_string(), "b".to_string(), "c".to_string()],
&mut Vec::new(),
&mut node_b,
);
helper(
&mut root,
&mut vec!["a".to_string(), "b".to_string(), "d".to_string()],
&mut vec!["d".to_string()],
&mut node_b,
);
helper(
&mut root,
&mut vec!["b".to_string()],
&mut vec!["b".to_string()],
&mut root,
);
}
}
However, I am getting the errors
- [E0499]: cannot borrow
*root
as mutable more than once at a time - [E0505]: cannot move out of
root
because it is borrowed
I am not sure how to address these. Any helpful suggestions are appreciated.