Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Use Rust's flat_map() With Recursive Structs

There's probably a better way to do this and I wouldn't be surprised to learn there are bugs with this approach, but this is working for me

Code

#[derive(Debug)]
pub struct Widget {
  id: String,
  children: Vec<Widget>
}

fn main() {
  let mut flattened = vec![];
  let tree = vec![
    Widget {
      id: "l1a".to_string(), 
      children: vec![
        Widget {
          id: "l2a".to_string(),
          children: vec![
            Widget {
              id: "l3a".to_string(),
              children: vec![]
            }, 
            Widget {
              id: "l3b".to_string(),
              children: vec![]
            }
          ]
        }, 
        Widget {
          id: "l2b".to_string(),
          children: vec![]
        }
      ]
    }, 
    Widget {
      id: "l1b".to_string(),
      children: vec![]
    }
  ];
  flattener(&tree, &mut flattened);
  dbg!(flattened);
}

pub fn flattener(items: &Vec<Widget>, dest: &mut Vec<String>) {
  items.iter().for_each(|item| 
    {
      dest.push(item.id.to_string());
      flattener(&item.children, dest);
    }
  );
}

Results

[_active_nvim_run:38:3] flattened = [
    "l1a",
    "l2a",
    "l3a",
    "l3b",
    "l2b",
    "l1b",
]