forked from rojo-rbx/rojo
Force PathMap to have deterministic ordering by using BTreeSet instead of HashSet
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{BTreeSet, HashMap},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ use serde::Serialize;
|
|||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct PathMapNode<T> {
|
struct PathMapNode<T> {
|
||||||
value: T,
|
value: T,
|
||||||
children: HashSet<PathBuf>,
|
children: BTreeSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A map from paths to another type, like instance IDs, with a bit of
|
/// A map from paths to another type, like instance IDs, with a bit of
|
||||||
@@ -25,7 +25,7 @@ pub struct PathMap<T> {
|
|||||||
/// Note that these paths may have other _ancestors_ in the tree, but if an
|
/// Note that these paths may have other _ancestors_ in the tree, but if an
|
||||||
/// orphan's parent path is ever inserted, it will stop being an orphan. It
|
/// orphan's parent path is ever inserted, it will stop being an orphan. It
|
||||||
/// will be... adopted!
|
/// will be... adopted!
|
||||||
orphan_paths: HashSet<PathBuf>,
|
orphan_paths: BTreeSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for PathMap<T> {
|
impl<T> Default for PathMap<T> {
|
||||||
@@ -38,7 +38,7 @@ impl<T> PathMap<T> {
|
|||||||
pub fn new() -> PathMap<T> {
|
pub fn new() -> PathMap<T> {
|
||||||
PathMap {
|
PathMap {
|
||||||
nodes: HashMap::new(),
|
nodes: HashMap::new(),
|
||||||
orphan_paths: HashSet::new(),
|
orphan_paths: BTreeSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ impl<T> PathMap<T> {
|
|||||||
|
|
||||||
// Collect any children that are currently marked as orphaned paths, but
|
// Collect any children that are currently marked as orphaned paths, but
|
||||||
// are actually children of this new node.
|
// are actually children of this new node.
|
||||||
let mut children = HashSet::new();
|
let mut children = BTreeSet::new();
|
||||||
for orphan_path in &self.orphan_paths {
|
for orphan_path in &self.orphan_paths {
|
||||||
if orphan_path.parent() == Some(&path) {
|
if orphan_path.parent() == Some(&path) {
|
||||||
children.insert(orphan_path.clone());
|
children.insert(orphan_path.clone());
|
||||||
@@ -158,7 +158,7 @@ impl<T> PathMap<T> {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use maplit::hashset;
|
use maplit::btreeset;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn smoke_test() {
|
fn smoke_test() {
|
||||||
@@ -179,10 +179,10 @@ mod test {
|
|||||||
let mut map = PathMap::new();
|
let mut map = PathMap::new();
|
||||||
|
|
||||||
map.insert("/foo/bar", 5);
|
map.insert("/foo/bar", 5);
|
||||||
assert_eq!(map.orphan_paths, hashset!["/foo/bar".into()]);
|
assert_eq!(map.orphan_paths, btreeset!["/foo/bar".into()]);
|
||||||
|
|
||||||
map.insert("/foo", 6);
|
map.insert("/foo", 6);
|
||||||
assert_eq!(map.orphan_paths, hashset!["/foo".into()]);
|
assert_eq!(map.orphan_paths, btreeset!["/foo".into()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -246,4 +246,37 @@ mod test {
|
|||||||
assert_eq!(map.get("/foo"), None);
|
assert_eq!(map.get("/foo"), None);
|
||||||
assert_eq!(map.get("/foo/bar/baz"), Some(&12));
|
assert_eq!(map.get("/foo/bar/baz"), Some(&12));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Makes sure that regardless of addition order, paths are always sorted
|
||||||
|
// when asking for children.
|
||||||
|
#[test]
|
||||||
|
fn add_order_sorted() {
|
||||||
|
let mut map = PathMap::new();
|
||||||
|
|
||||||
|
map.insert("/foo", 5);
|
||||||
|
map.insert("/foo/b", 2);
|
||||||
|
map.insert("/foo/d", 0);
|
||||||
|
map.insert("/foo/c", 3);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
map.children("/foo"),
|
||||||
|
Some(vec![
|
||||||
|
Path::new("/foo/b"),
|
||||||
|
Path::new("/foo/c"),
|
||||||
|
Path::new("/foo/d"),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
map.insert("/foo/a", 1);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
map.children("/foo"),
|
||||||
|
Some(vec![
|
||||||
|
Path::new("/foo/a"),
|
||||||
|
Path::new("/foo/b"),
|
||||||
|
Path::new("/foo/c"),
|
||||||
|
Path::new("/foo/d"),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user