Topologically sort names so parents come before children. Collects `(Address, Name)` pairs up front (cheap: Arc clone + 32-byte address clone), parallel-sorts by address for canonical DFS order, then walks each entry via the Arc parent chain in `NameData::Str`/`Num`. The DFS recurses through those Arc pointers — parents are NOT looked up in the DashMap, which is why the result retains `Name` valu
( names: &crate::map::IxonMap<Address, Name>, )
| 2086 | // Section 3: anon_hints (§2-index keyed; resolved via consts_order) |
| 2087 | for (addr, hints) in read_hints_section( |
| 2088 | buf, |
| 2089 | consts_order.len(), |
| 2090 | |i| consts_order[i].clone(), |
| 2091 | "Env::get", |
| 2092 | )? { |
| 2093 | env.anon_hints.insert(addr, hints); |
| 2094 | } |
| 2095 | |
| 2096 | // Section 4: Names (build lookup table and reverse index for metadata) |
| 2097 | let num_names = get_u64(buf)?; |
| 2098 | let mut names_lookup: FxHashMap<Address, Name> = FxHashMap::default(); |
| 2099 | let mut name_reverse_index: NameReverseIndex = |
| 2100 | Vec::with_capacity(num_names as usize + 1); |
| 2101 | // Anonymous name is serialized first (index 0) — read it from the stream |
| 2102 | // along with all other names below. But pre-seed the lookup so name |
| 2103 | // reconstruction works for names whose parent is anonymous. |
| 2104 | let anon_addr = Address::from_blake3_hash(*Name::anon().get_hash()); |
| 2105 | names_lookup.insert(anon_addr.clone(), Name::anon()); |
| 2106 | env.names.insert(anon_addr, Name::anon()); |
| 2107 | for _ in 0..num_names { |
| 2108 | let addr = get_address(buf)?; |
| 2109 | let name = get_name_component(buf, &names_lookup)?; |
| 2110 | name_reverse_index.push(addr.clone()); |
| 2111 | names_lookup.insert(addr.clone(), name.clone()); |
| 2112 | env.names.insert(addr, name); |
| 2113 | } |
| 2114 | |
| 2115 | // Section 5: Named (use indexed deserialization for metadata) |
| 2116 | let num_named = get_u64(buf)?; |
| 2117 | for _ in 0..num_named { |
| 2118 | let name_idx = get_u64(buf)? as usize; |
| 2119 | let name_addr = |
| 2120 | name_reverse_index.get(name_idx).cloned().ok_or_else(|| { |
| 2121 | format!( |
| 2122 | "Env::get: §5 name index {name_idx} out of range ({} \ |
| 2123 | names){PRE_COMPACT_KEYS}", |
| 2124 | name_reverse_index.len() |
| 2125 | ) |
| 2126 | })?; |
| 2127 | let mut named = get_named_indexed( |
| 2128 | buf, |
| 2129 | &name_reverse_index, |
| 2130 | ConstGet::Addrs(&consts_order), |
| 2131 | )?; |
| 2132 | if demote_named { |
| 2133 | named.demote(); |
| 2134 | } |
| 2135 | let name = names_lookup.get(&name_addr).cloned().ok_or_else(|| { |
| 2136 | format!("Env::get: missing name for addr {:?}", name_addr) |
| 2137 | })?; |
| 2138 | env.named.insert(name, named); |
| 2139 | } |
| 2140 | |
| 2141 | // Section 6: Comms |
| 2142 | let num_comms = get_u64(buf)?; |