Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created May 29, 2022 07:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rust-play/322e7b57f612de68a76bf2b6107d60f9 to your computer and use it in GitHub Desktop.
Save rust-play/322e7b57f612de68a76bf2b6107d60f9 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
use std::collections::HashMap;
// use std::rc::Rc;
// use std::cell::{RefCell, RefMut};
fn main() {
// This code simulates an insert() function.
let mut m = M { children: HashMap::new() };
let mut mb = M { children: HashMap::new() };
let mut mc: M = M { children: HashMap::new() };
let mut md: M = M { children: HashMap::new() };
let me: M = M { children: HashMap::new() };
md.children.insert("weld".to_string(), me);
mc.children.insert("nut".to_string(), md);
mb.children.insert("washer".to_string(), mc);
m.children.insert("bolt".to_string(), mb);
////////
// Prove to ourselves that the normal find() function works.
let a_success = m.find(vec!["bolt", "washer", "nut"]);
match a_success {
Ok(child) => println!("Successful success: {:?}", child),
Err(msg) => println!("Failed success: {}", msg)
}
let another_success = m.find(vec!["bolt", "washer", "nut", "weld"]);
match another_success {
Ok(child) => println!("Successful success: {:?}", child),
Err(msg) => println!("Failed success: {}", msg)
}
let a_failure = m.find(vec!["nut", "washer", "bolt"]);
match a_failure {
Ok(child) => println!("Failed failure: {:?}", child),
Err(msg) => println!("Successful failure: {}", msg)
}
let another_failure = m.find(vec!["weld"]);
match another_failure {
Ok(child) => println!("Failed failure: {:?}", child),
Err(msg) => println!("Successful failure: {}", msg)
}
// Desired usage pseudocode
// let mut m = M { children: HashMap::new() }
// m.insert(vec!["bolt", "washer"]);
// let blah = m.find_with_path(vec!["bolt", "washer"]);
// let new_m = blah.last(); // Washer M
// new_m.insert(vec!["nut", "weld"]);
// new_m.find(vec!["nut", "weld"]);
// m.find(vec!["bolt", "washer", "nut", "weld"]);
// Yay
// let another_m = blah[0]; // Bolt M
// another_m.find(vec!["washer"])
// Yay
// Profit
}
#[derive(Debug)]
struct M {
children: HashMap<String, M>
}
impl M {
fn find(&mut self, key: Vec<&str>) -> Result<&mut M, String> {
let mut current = Some(self);
for key_part in key[..].to_vec() {
match current.and_then(|item| item.children.get_mut(key_part)) {
Some(child) => current = Some(child),
None => current = None
}
}
match current {
Some(child) => Ok(child),
None => Err(format!("Unable to locate key [{}]", key.join(", ")))
}
}
fn find_with_path(&mut self, key: Vec<&str>) /* -> Some list of Ms */ {
let mut current = Some(self);
// let path: Vec<something> = Vec::new()
// ^^ Some structure to hold references to
// each M we successfully find, to be
// returned to caller
for key_part in key[..].to_vec() {
match current.and_then(|item| item.children.get_mut(key_part)) {
Some(child) => {
// Similar to other find function, but every time we
// successfully find another child M, we push it
// onto a list of some kind that can be returned to
// the caller. We then move onto the child and the
// next piece of the key, as in the other find
// function.
//
// Magic goes here. Somehow store reference in a
// list or other structure that will allow me to
// return a group of Ms or references to Ms to
// the caller. The caller must be able to get
// his hands on mutable versions of the Ms so
// as to call additional methods on them.
//
// I've tried various approaches. For a minute,
// I thought Rc/RefCell might save me, but I
// couldn't figure out how to store
// Rc<RefCell<&M>>s from current or child,
// because those belong to this function and/or
// this match arm.
current = Some(child)
},
None => current = None
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment