diff --git a/src/generator.rs b/src/generator.rs index a3b18caa..00c7b3a8 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -22,8 +22,8 @@ use crate::prepare::resolve_ref_name; use crate::types::NixOption; use crate::types::NixType; use serde_json::Value; -use std::collections::HashMap; -use std::collections::HashSet; +use std::collections::BTreeMap; +use std::collections::BTreeSet; /// Configuration options for the generator #[derive(Debug, Clone)] @@ -56,13 +56,13 @@ pub enum GeneratorError { /// The main Nix code generator pub struct Generator { - definitions: HashMap, + definitions: BTreeMap, /// Cache for resolved type definitions to avoid infinite recursion resolving: Vec, /// Count of how many times each $def is referenced - ref_counts: HashMap, + ref_counts: BTreeMap, /// Pre-generated types for frequently used definitions - type_bindings: HashMap, + type_bindings: BTreeMap, /// Whether we're in the second pass (using type refs) use_type_refs: bool, } @@ -73,8 +73,8 @@ impl Generator { Self { definitions: collect_definitions(schema), resolving: Vec::new(), - ref_counts: HashMap::new(), - type_bindings: HashMap::new(), + ref_counts: BTreeMap::new(), + type_bindings: BTreeMap::new(), use_type_refs: false, } } @@ -149,9 +149,9 @@ impl Generator { } /// Build a dependency graph of $defs - /// Returns HashMap> - fn build_dependency_graph(&self) -> HashMap> { - let mut graph: HashMap> = HashMap::new(); + /// Returns BTreeMap> + fn build_dependency_graph(&self) -> BTreeMap> { + let mut graph: BTreeMap> = BTreeMap::new(); for (name, def) in &self.definitions { let deps = Self::collect_refs_in_schema(def); @@ -233,10 +233,10 @@ impl Generator { } /// Topologically sort definitions so dependencies come before dependents - fn topological_sort(graph: &HashMap>) -> Vec { + fn topological_sort(graph: &BTreeMap>) -> Vec { let mut result = Vec::new(); - let mut visited = HashSet::new(); - let mut temp_visited = HashSet::new(); // For cycle detection + let mut visited = BTreeSet::new(); + let mut temp_visited = BTreeSet::new(); // For cycle detection for name in graph.keys() { Self::topo_visit(name, graph, &mut visited, &mut temp_visited, &mut result); @@ -248,9 +248,9 @@ impl Generator { /// DFS visit for topological sort fn topo_visit( name: &str, - graph: &HashMap>, - visited: &mut HashSet, - temp_visited: &mut HashSet, + graph: &BTreeMap>, + visited: &mut BTreeSet, + temp_visited: &mut BTreeSet, result: &mut Vec, ) { if visited.contains(name) { @@ -286,7 +286,7 @@ impl Generator { let sorted_defs = Self::topological_sort(&graph); // Only generate bindings for refs used more than once - let frequent_refs: HashSet = self + let frequent_refs: BTreeSet = self .ref_counts .iter() .filter(|&(_, &count)| count > 1) @@ -480,7 +480,7 @@ impl Generator { // Collect all other properties from all variants (excluding the discriminator) // Track property types to merge them if they differ across variants - let mut prop_types: HashMap> = HashMap::new(); + let mut prop_types: BTreeMap> = BTreeMap::new(); for (_, variant_schema) in &variants { if let Some(props) = variant_schema.get("properties").and_then(|p| p.as_object()) { diff --git a/src/prepare.rs b/src/prepare.rs index f83173e7..d9ae4dc5 100644 --- a/src/prepare.rs +++ b/src/prepare.rs @@ -1,15 +1,15 @@ //! Schema preparation utilities for normalizing JSON Schema before conversion use serde_json::Value; -use std::collections::HashMap; +use std::collections::BTreeMap; /// Result type for mixed enum + object union detection /// Contains (enum_variants, object_variants) where object_variants are (tag_name, inner_schema) tuples pub type MixedUnionResult = (Vec, Vec<(String, Value)>); /// Extract all definitions from the schema's $defs section -pub fn collect_definitions(schema: &Value) -> HashMap { - let mut defs = HashMap::new(); +pub fn collect_definitions(schema: &Value) -> BTreeMap { + let mut defs = BTreeMap::new(); if let Some(definitions) = schema.get("$defs").and_then(|d| d.as_object()) { for (name, def) in definitions {