diff --git a/src/config/acl.rs b/src/config/acl.rs index 16f2a17d..0105e041 100644 --- a/src/config/acl.rs +++ b/src/config/acl.rs @@ -1,5 +1,5 @@ use std::io::Write; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, BTreeMap, BTreeSet}; use std::path::{PathBuf, Path}; use failure::*; @@ -70,7 +70,7 @@ pub struct AclTree { struct AclTreeNode { users: HashMap>, groups: HashMap>, - children: HashMap, + children: BTreeMap, } impl AclTreeNode { @@ -79,7 +79,7 @@ impl AclTreeNode { Self { users: HashMap::new(), groups: HashMap::new(), - children: HashMap::new(), + children: BTreeMap::new(), } } @@ -197,10 +197,10 @@ impl AclTree { let role = role.as_str(); let user = user.to_string(); if *propagate { - role_ug_map1.entry(role).or_insert_with(|| HashSet::new()) + role_ug_map1.entry(role).or_insert_with(|| BTreeSet::new()) .insert(user); } else { - role_ug_map0.entry(role).or_insert_with(|| HashSet::new()) + role_ug_map0.entry(role).or_insert_with(|| BTreeSet::new()) .insert(user); } } @@ -210,60 +210,53 @@ impl AclTree { for (role, propagate) in roles { let group = format!("@{}", group); if *propagate { - role_ug_map1.entry(role).or_insert_with(|| HashSet::new()) + role_ug_map1.entry(role).or_insert_with(|| BTreeSet::new()) .insert(group); } else { - role_ug_map0.entry(role).or_insert_with(|| HashSet::new()) + role_ug_map0.entry(role).or_insert_with(|| BTreeSet::new()) .insert(group); } } } fn group_by_property_list( - item_property_map: &HashMap<&str, HashSet>, - ) -> HashMap> { - let mut result_map = HashMap::new(); + item_property_map: &HashMap<&str, BTreeSet>, + ) -> BTreeMap> { + let mut result_map = BTreeMap::new(); for (item, property_map) in item_property_map { - let mut item_list = property_map.iter().map(|v| v.as_str()) - .collect::>(); - item_list.sort(); - let item_list = item_list.join(","); - result_map.entry(item_list).or_insert_with(|| HashSet::new()) + let item_list = property_map.iter().fold(String::new(), |mut acc, v| { + if !acc.is_empty() { acc.push(','); } + acc.push_str(v); + acc + }); + result_map.entry(item_list).or_insert_with(|| BTreeSet::new()) .insert(item.to_string()); } result_map } - let mut uglist_role_map0 = group_by_property_list(&role_ug_map0) - .into_iter() - .collect::)>>(); - uglist_role_map0.sort_unstable_by(|a,b| a.0.cmp(&b.0)); - - let mut uglist_role_map1 = group_by_property_list(&role_ug_map1) - .into_iter() - .collect::)>>(); - uglist_role_map1.sort_unstable_by(|a,b| a.0.cmp(&b.0)); - + let uglist_role_map0 = group_by_property_list(&role_ug_map0); + let uglist_role_map1 = group_by_property_list(&role_ug_map1); for (uglist, roles) in uglist_role_map0 { - let mut role_list = roles.iter().map(|v| v.as_str()) - .collect::>(); - role_list.sort(); - writeln!(w, "acl:0:{}:{}:{}", path, uglist, role_list.join(","))?; + let role_list = roles.iter().fold(String::new(), |mut acc, v| { + if !acc.is_empty() { acc.push(','); } + acc.push_str(v); + acc + }); + writeln!(w, "acl:0:{}:{}:{}", path, uglist, role_list)?; } for (uglist, roles) in uglist_role_map1 { - let mut role_list = roles.iter().map(|v| v.as_str()) - .collect::>(); - role_list.sort(); - writeln!(w, "acl:1:{}:{}:{}", path, uglist, role_list.join(","))?; + let role_list = roles.iter().fold(String::new(), |mut acc, v| { + if !acc.is_empty() { acc.push(','); } + acc.push_str(v); + acc + }); + writeln!(w, "acl:1:{}:{}:{}", path, uglist, role_list)?; } - let mut child_names = node.children.keys().map(|v| v.as_str()).collect::>(); - child_names.sort(); - - for name in child_names { - let child = node.children.get(name).unwrap(); + for (name, child) in node.children.iter() { let child_path = format!("{}/{}", path, name); Self::write_node_config(child, &child_path, w)?; }