yabe/
sorter.rs

1use yaml_rust2::yaml::{Array, Hash, Yaml};
2use std::borrow::Cow;
3
4pub fn sort_yaml<'a>(doc: &'a Yaml, config: &Yaml) -> Cow<'a, Yaml> {
5    match doc {
6        Yaml::Array(v) => {
7            if let Some(sort_key) = config["sortKey"].as_str() {
8                let mut new_v = v.clone();
9                array_sorter(&mut new_v, sort_key);
10                for x in &mut new_v {
11                    let sorted = sort_yaml(x, config);
12                    *x = sorted.into_owned();
13                }
14                Cow::Owned(Yaml::Array(new_v))
15            } else {
16                Cow::Borrowed(doc)
17            }
18        }
19        Yaml::Hash(h) => {
20            if let Some(pre_order_vec) = config["preOrder"].as_vec() {
21                let mut new_h = h.clone();
22                let pre_order = pre_order_vec
23                    .iter()
24                    .filter_map(|x| x.as_str())
25                    .collect::<Vec<&str>>();
26                hash_sorter(&mut new_h, &pre_order);
27                for (_, v) in &mut new_h {
28                    let sorted = sort_yaml(v, config);
29                    *v = sorted.into_owned();
30                }
31                Cow::Owned(Yaml::Hash(new_h))
32            } else {
33                Cow::Borrowed(doc)
34            }
35        }
36        _ => Cow::Borrowed(doc),
37    }
38}
39
40pub fn hash_sorter(hash: &mut Hash, pre_order: &[&str]) {
41    let mut result = Hash::new();
42
43    // Sort the hash by the pre_order array
44    for key in pre_order {
45        if let Some((k, v)) = hash.remove_entry(&Yaml::String((*key).to_string())) {
46            result.insert(k, v);
47        }
48    }
49
50    // Collect the remaining keys
51    let mut hash_keys: Vec<Yaml> = hash.keys().cloned().collect();
52    hash_keys.sort_by(|a, b| a.cmp(b));
53
54    for key in hash_keys {
55        if let Some((k, v)) = hash.remove_entry(&key) {
56            result.insert(k, v);
57        }
58    }
59
60    *hash = result;
61}
62
63pub fn array_sorter(array: &mut Array, sort_key: &str) {
64    array.sort_by(|a, b| match (a[sort_key].as_str(), b[sort_key].as_str()) {
65        (Some(a_str), Some(b_str)) => a_str.cmp(b_str),
66        (Some(_), None) => std::cmp::Ordering::Less,
67        (None, Some(_)) => std::cmp::Ordering::Greater,
68        (None, None) => std::cmp::Ordering::Equal,
69    });
70}