1use std::collections::{HashMap, HashSet};
7
8use crate::ast::{Declaration, DeclSpecs, Declarator, DerivedDecl, ExternalDecl, StorageClass, StructMember, StructSpec, TypeSpec};
9use crate::intern::{InternedStr, StringInterner};
10use crate::type_repr::TypeRepr;
11
12#[derive(Debug, Clone)]
14pub struct CommonField {
15 pub name: InternedStr,
17 pub is_fn_pointer: bool,
19 pub origin: CommonFieldOrigin,
21}
22
23#[derive(Debug, Clone)]
25pub enum CommonFieldOrigin {
26 Direct,
28 InsideUnion { union_field: InternedStr },
30}
31
32#[derive(Debug, Clone)]
34pub struct CommonFieldMacro {
35 pub name: InternedStr,
36 pub fields: Vec<CommonField>,
37}
38
39fn is_fn_pointer_declarator(derived: &[DerivedDecl]) -> bool {
46 let has_fn = derived.iter().any(|d| matches!(d, DerivedDecl::Function(_)));
47 let has_ptr = derived.iter().any(|d| matches!(d, DerivedDecl::Pointer(_)));
48 has_fn && has_ptr
49}
50
51fn flexible_array_element_type(ty: &TypeRepr) -> Option<TypeRepr> {
57 use crate::type_repr::CDerivedType;
58 let TypeRepr::CType { specs, derived, source } = ty else {
59 return None;
60 };
61 let last = derived.last()?;
62 let is_flex = match last {
63 CDerivedType::Array { size: None } => true,
64 CDerivedType::Array { size: Some(0) } | CDerivedType::Array { size: Some(1) } => true,
65 _ => false,
66 };
67 if !is_flex {
68 return None;
69 }
70 let mut new_derived = derived.clone();
71 new_derived.pop();
72 Some(TypeRepr::CType {
73 specs: specs.clone(),
74 derived: new_derived,
75 source: source.clone(),
76 })
77}
78
79#[derive(Debug, Clone)]
81pub struct FieldType {
82 pub type_repr: TypeRepr,
84}
85
86#[derive(Debug, Default)]
88pub struct FieldsDict {
89 field_to_structs: HashMap<InternedStr, HashSet<InternedStr>>,
92 field_types: HashMap<(InternedStr, InternedStr), FieldType>,
94 typedef_to_struct: HashMap<InternedStr, InternedStr>,
96 consistent_type_cache: HashMap<InternedStr, Option<TypeRepr>>,
98 sv_family_members: HashSet<InternedStr>,
101 sv_head_type_to_struct: HashMap<String, InternedStr>,
105 sv_u_field_types: HashMap<InternedStr, String>,
109 struct_to_common_macros: HashMap<InternedStr, Vec<InternedStr>>,
112 common_macro_to_structs: HashMap<InternedStr, Vec<InternedStr>>,
115 common_macros: HashMap<InternedStr, CommonFieldMacro>,
118 field_to_defining_macro: HashMap<InternedStr, InternedStr>,
122 common_field_rust_types: HashMap<InternedStr, TypeRepr>,
125 common_macro_to_sv_family: HashMap<InternedStr, InternedStr>,
130 flexible_array_fields: HashMap<(InternedStr, InternedStr), TypeRepr>,
135 struct_defs: HashMap<InternedStr, StructDef>,
140}
141
142#[derive(Debug, Clone)]
147pub struct StructDef {
148 pub name: InternedStr,
149 pub is_union: bool,
150 pub members: Vec<StructMemberInfo>,
151}
152
153#[derive(Debug, Clone)]
155pub struct StructMemberInfo {
156 pub name: InternedStr,
157 pub type_repr: TypeRepr,
158 pub bitfield_width: Option<u32>,
160}
161
162impl FieldsDict {
163 pub fn new() -> Self {
165 Self::default()
166 }
167
168 pub fn collect_from_external_decl(
171 &mut self,
172 decl: &ExternalDecl,
173 is_target: bool,
174 interner: &StringInterner,
175 ) {
176 if !is_target {
178 return;
179 }
180
181 if let ExternalDecl::Declaration(d) = decl {
182 self.collect_from_declaration(d, interner);
183 }
184 }
185
186 fn collect_from_declaration(&mut self, decl: &Declaration, interner: &StringInterner) {
188 if decl.specs.storage == Some(StorageClass::Typedef) {
190 self.collect_typedef_aliases(decl, interner);
191 self.collect_typedef_anonymous_struct(decl, interner);
195 }
196
197 for type_spec in &decl.specs.type_specs {
198 match type_spec {
199 TypeSpec::Struct(spec) => {
200 self.collect_from_struct_spec_with_kind(spec, false, interner);
201 }
202 TypeSpec::Union(spec) => {
203 self.collect_from_struct_spec_with_kind(spec, true, interner);
205 }
206 _ => {}
207 }
208 }
209 }
210
211 fn collect_typedef_anonymous_struct(&mut self, decl: &Declaration, interner: &StringInterner) {
216 let (anon_spec, is_union) = {
218 let mut found = None;
219 for ts in &decl.specs.type_specs {
220 match ts {
221 TypeSpec::Struct(s) if s.name.is_none() && s.members.is_some() => {
222 found = Some((s, false));
223 break;
224 }
225 TypeSpec::Union(s) if s.name.is_none() && s.members.is_some() => {
226 found = Some((s, true));
227 break;
228 }
229 _ => {}
230 }
231 }
232 match found {
233 Some(v) => v,
234 None => return,
235 }
236 };
237
238 for init_decl in &decl.declarators {
240 if !init_decl.declarator.derived.is_empty() {
241 continue;
242 }
243 let typedef_name = match init_decl.declarator.name {
244 Some(n) => n,
245 None => continue,
246 };
247 let synthetic_spec = StructSpec {
249 name: Some(typedef_name),
250 members: anon_spec.members.clone(),
251 loc: anon_spec.loc.clone(),
252 };
253 self.collect_from_struct_spec_with_kind(&synthetic_spec, is_union, interner);
254 }
255 }
256
257 fn collect_typedef_aliases(&mut self, decl: &Declaration, _interner: &StringInterner) {
260 let mut struct_name: Option<InternedStr> = None;
262 for type_spec in &decl.specs.type_specs {
263 match type_spec {
264 TypeSpec::Struct(spec) | TypeSpec::Union(spec) => {
265 if let Some(name) = spec.name {
266 struct_name = Some(name);
267 break;
268 }
269 }
270 _ => {}
271 }
272 }
273
274 if let Some(s_name) = struct_name {
276 for init_decl in &decl.declarators {
277 if init_decl.declarator.derived.is_empty() {
281 if let Some(typedef_name) = init_decl.declarator.name {
282 self.typedef_to_struct.insert(typedef_name, s_name);
283 }
284 }
285 }
286 }
287 }
288
289 fn collect_from_struct_spec_with_kind(
291 &mut self, spec: &StructSpec, is_union: bool, interner: &StringInterner,
292 ) {
293 let struct_name = match spec.name {
295 Some(name) => name,
296 None => return,
297 };
298
299 let members = match &spec.members {
301 Some(m) => m,
302 None => return,
303 };
304
305 let mut ordered_members: Vec<StructMemberInfo> = Vec::new();
307
308 let last_idx = members.len().saturating_sub(1);
309 for (m_idx, member) in members.iter().enumerate() {
310 for type_spec in &member.specs.type_specs {
312 match type_spec {
313 TypeSpec::Struct(nested) => {
314 self.collect_from_struct_spec_with_kind(nested, false, interner);
315 }
316 TypeSpec::Union(nested) => {
317 self.collect_from_struct_spec_with_kind(nested, true, interner);
318 if self.is_sv_u_union_member(member, interner) {
320 self.collect_sv_u_union_fields(nested, interner);
321 }
322 }
323 _ => {}
324 }
325 }
326
327 let is_last_member = m_idx == last_idx;
329 let last_decl_idx = member.declarators.len().saturating_sub(1);
330 for (d_idx, decl) in member.declarators.iter().enumerate() {
331 if let Some(ref declarator) = decl.declarator {
332 if let Some(field_name) = declarator.name {
333 self.field_to_structs
335 .entry(field_name)
336 .or_insert_with(HashSet::new)
337 .insert(struct_name);
338
339 if let Some(type_repr) = self.extract_field_type(&member.specs, declarator, interner) {
341 let bitfield_width = decl.bitfield.as_ref().and_then(|e| {
343 if let crate::ast::ExprKind::IntLit(n) = &e.kind {
344 Some(*n as u32)
345 } else { None }
346 });
347 ordered_members.push(StructMemberInfo {
348 name: field_name,
349 type_repr: type_repr.clone(),
350 bitfield_width,
351 });
352
353 let is_struct_last = is_last_member && d_idx == last_decl_idx;
356 if is_struct_last {
357 if let Some(elem) = flexible_array_element_type(&type_repr) {
358 self.flexible_array_fields
359 .insert((struct_name, field_name), elem);
360 }
361 }
362 self.field_types.insert(
363 (struct_name, field_name),
364 FieldType { type_repr },
365 );
366 }
367 }
368 }
369 }
370 }
371
372 if !ordered_members.is_empty() {
374 self.struct_defs.entry(struct_name).or_insert_with(|| StructDef {
375 name: struct_name,
376 is_union,
377 members: ordered_members,
378 });
379 }
380 }
381
382 pub fn get_struct_def(&self, name: InternedStr) -> Option<&StructDef> {
384 self.struct_defs.get(&name)
385 }
386
387 pub fn member_type(&self, struct_name: InternedStr, member: InternedStr)
389 -> Option<&TypeRepr>
390 {
391 if let Some(def) = self.struct_defs.get(&struct_name) {
393 for m in &def.members {
394 if m.name == member {
395 return Some(&m.type_repr);
396 }
397 }
398 }
399 let resolved = self.typedef_to_struct.get(&struct_name).copied().unwrap_or(struct_name);
401 if resolved != struct_name {
402 if let Some(def) = self.struct_defs.get(&resolved) {
403 for m in &def.members {
404 if m.name == member {
405 return Some(&m.type_repr);
406 }
407 }
408 }
409 }
410 None
411 }
412
413 pub fn iter_struct_defs(&self) -> impl Iterator<Item = (&InternedStr, &StructDef)> {
415 self.struct_defs.iter()
416 }
417
418 fn is_sv_u_union_member(&self, member: &crate::ast::StructMember, interner: &StringInterner) -> bool {
420 for decl in &member.declarators {
422 if let Some(ref declarator) = decl.declarator {
423 if let Some(name) = declarator.name {
424 if interner.get(name) == "sv_u" {
425 return true;
426 }
427 }
428 }
429 }
430 false
431 }
432
433 fn collect_sv_u_union_fields(&mut self, union_spec: &StructSpec, interner: &StringInterner) {
437 let members = match &union_spec.members {
438 Some(m) => m,
439 None => return,
440 };
441
442 for member in members {
443 for struct_decl in &member.declarators {
444 if let Some(ref declarator) = struct_decl.declarator {
445 if let Some(field_name) = declarator.name {
446 if let Some(c_type) = self.extract_c_type(&member.specs, declarator, interner) {
448 self.register_sv_u_field(field_name, c_type);
449 }
450 }
451 }
452 }
453 }
454 }
455
456 fn extract_c_type(&self, specs: &DeclSpecs, declarator: &Declarator, interner: &StringInterner) -> Option<String> {
458 let base_type = self.extract_c_base_type(specs, interner)?;
460
461 let mut result = base_type;
463 for derived in &declarator.derived {
464 if let DerivedDecl::Pointer { .. } = derived {
465 result = format!("{}*", result);
466 }
467 }
468
469 Some(result)
470 }
471
472 fn extract_c_base_type(&self, specs: &DeclSpecs, interner: &StringInterner) -> Option<String> {
474 for type_spec in &specs.type_specs {
475 match type_spec {
476 TypeSpec::Void => return Some("void".to_string()),
477 TypeSpec::Char => return Some("char".to_string()),
478 TypeSpec::Int => return Some("int".to_string()),
479 TypeSpec::Short => return Some("short".to_string()),
480 TypeSpec::Long => return Some("long".to_string()),
481 TypeSpec::Float => return Some("float".to_string()),
482 TypeSpec::Double => return Some("double".to_string()),
483 TypeSpec::Unsigned => continue, TypeSpec::Signed => continue,
485 TypeSpec::Struct(s) | TypeSpec::Union(s) => {
486 if let Some(name) = s.name {
487 return Some(interner.get(name).to_string());
488 }
489 }
490 TypeSpec::TypedefName(name) => {
491 return Some(interner.get(*name).to_string());
492 }
493 _ => {}
494 }
495 }
496 None
497 }
498
499 fn extract_field_type(&self, specs: &DeclSpecs, declarator: &Declarator, interner: &StringInterner) -> Option<TypeRepr> {
501 Some(TypeRepr::from_decl(specs, declarator, interner))
503 }
504
505 pub fn lookup_unique(&self, field_name: InternedStr) -> Option<InternedStr> {
507 self.field_to_structs.get(&field_name).and_then(|structs| {
508 if structs.len() == 1 {
509 structs.iter().next().copied()
510 } else {
511 None
512 }
513 })
514 }
515
516 pub fn get_consistent_base_type(&self, field_name: InternedStr, interner: &StringInterner) -> Option<InternedStr> {
527 let structs = self.field_to_structs.get(&field_name)?;
528
529 if structs.is_empty() {
531 return None;
532 }
533
534 let all_sv_family = structs.iter().all(|s| self.sv_family_members.contains(s));
536
537 if all_sv_family {
538 interner.lookup("sv")
542 } else {
543 None
544 }
545 }
546
547 pub fn get_unique_field_type(&self, field_name: InternedStr) -> Option<&FieldType> {
549 let struct_name = self.lookup_unique(field_name)?;
550 self.field_types.get(&(struct_name, field_name))
551 }
552
553 pub fn get_field_type(
555 &self,
556 struct_name: InternedStr,
557 field_name: InternedStr,
558 ) -> Option<&FieldType> {
559 if let Some(ft) = self.field_types.get(&(struct_name, field_name)) {
561 return Some(ft);
562 }
563 let resolved = self.resolve_typedef(struct_name)?;
565 self.field_types.get(&(resolved, field_name))
566 }
567
568 pub fn get_field_type_by_name(
572 &self,
573 struct_name_str: &str,
574 field_name: InternedStr,
575 interner: &StringInterner,
576 ) -> Option<&FieldType> {
577 for ((s_name, f_name), field_type) in &self.field_types {
579 if interner.get(*s_name) == struct_name_str && *f_name == field_name {
580 return Some(field_type);
581 }
582 }
583
584 if let Some(resolved_struct_name) = self.resolve_typedef_by_name(struct_name_str, interner) {
586 let resolved_str = interner.get(resolved_struct_name);
587 for ((s_name, f_name), field_type) in &self.field_types {
588 if interner.get(*s_name) == resolved_str && *f_name == field_name {
589 return Some(field_type);
590 }
591 }
592 }
593
594 None
595 }
596
597 pub fn resolve_typedef(&self, typedef_name: InternedStr) -> Option<InternedStr> {
599 self.typedef_to_struct.get(&typedef_name).copied()
600 }
601
602 fn resolve_typedef_by_name(&self, typedef_name_str: &str, interner: &StringInterner) -> Option<InternedStr> {
604 for (typedef_name, struct_name) in &self.typedef_to_struct {
605 if interner.get(*typedef_name) == typedef_name_str {
606 return Some(*struct_name);
607 }
608 }
609 None
610 }
611
612 pub fn get_typedef_for_struct(&self, struct_name: InternedStr) -> Option<InternedStr> {
617 for (typedef_name, s_name) in &self.typedef_to_struct {
618 if *s_name == struct_name {
619 return Some(*typedef_name);
620 }
621 }
622 None
623 }
624
625 pub fn typedef_count(&self) -> usize {
627 self.typedef_to_struct.len()
628 }
629
630 pub fn iter_typedefs(&self) -> impl Iterator<Item = (&InternedStr, &InternedStr)> {
632 self.typedef_to_struct.iter()
633 }
634
635 pub fn field_types_count(&self) -> usize {
637 self.field_types.len()
638 }
639
640 pub fn add_sv_family_member_with_type(&mut self, struct_name: InternedStr, type_name: &str) {
649 self.sv_family_members.insert(struct_name);
650
651 let normalized = type_name.trim().trim_end_matches('*').trim();
653 if !normalized.is_empty() && normalized != "void" {
654 self.sv_head_type_to_struct.insert(normalized.to_string(), struct_name);
655 }
656 }
657
658 pub fn get_struct_for_sv_head_type(&self, type_name: &str) -> Option<InternedStr> {
663 let normalized = type_name.trim().trim_end_matches('*').trim();
664 self.sv_head_type_to_struct.get(normalized).copied()
665 }
666
667 pub fn is_sv_family_type(&self, type_name: InternedStr) -> bool {
669 if self.sv_family_members.contains(&type_name) {
671 return true;
672 }
673 if let Some(struct_name) = self.typedef_to_struct.get(&type_name) {
675 return self.sv_family_members.contains(struct_name);
676 }
677 false
678 }
679
680 pub fn sv_family_members_count(&self) -> usize {
682 self.sv_family_members.len()
683 }
684
685 pub fn sv_head_type_mapping_count(&self) -> usize {
687 self.sv_head_type_to_struct.len()
688 }
689
690 pub fn sv_head_type_to_struct_iter(&self) -> impl Iterator<Item = (&String, &InternedStr)> {
692 self.sv_head_type_to_struct.iter()
693 }
694
695 pub fn add_struct_uses_common_macro(
703 &mut self,
704 struct_name: InternedStr,
705 macro_name: InternedStr,
706 ) {
707 let v = self.struct_to_common_macros.entry(struct_name).or_default();
708 if !v.contains(¯o_name) {
709 v.push(macro_name);
710 }
711 let v = self.common_macro_to_structs.entry(macro_name).or_default();
712 if !v.contains(&struct_name) {
713 v.push(struct_name);
714 }
715 }
716
717 pub fn structs_using_common_macro(&self, macro_name: InternedStr) -> &[InternedStr] {
719 self.common_macro_to_structs
720 .get(¯o_name)
721 .map(|v| v.as_slice())
722 .unwrap_or(&[])
723 }
724
725 pub fn common_macros_used_by_struct(&self, struct_name: InternedStr) -> &[InternedStr] {
727 self.struct_to_common_macros
728 .get(&struct_name)
729 .map(|v| v.as_slice())
730 .unwrap_or(&[])
731 }
732
733 pub fn common_macro_count(&self) -> usize {
735 self.common_macro_to_structs.len()
736 }
737
738 pub fn defining_macro_of(&self, field_name: InternedStr) -> Option<InternedStr> {
740 self.field_to_defining_macro.get(&field_name).copied()
741 }
742
743 pub fn common_macro(&self, macro_name: InternedStr) -> Option<&CommonFieldMacro> {
745 self.common_macros.get(¯o_name)
746 }
747
748 pub fn canonical_field(
750 &self,
751 field_name: InternedStr,
752 ) -> Option<(&CommonFieldMacro, &CommonField)> {
753 let macro_name = *self.field_to_defining_macro.get(&field_name)?;
754 let cm = self.common_macros.get(¯o_name)?;
755 let cf = cm.fields.iter().find(|f| f.name == field_name)?;
756 Some((cm, cf))
757 }
758
759 pub fn rust_type_of_common_field(&self, field_name: InternedStr) -> Option<&TypeRepr> {
762 self.common_field_rust_types.get(&field_name)
763 }
764
765 pub fn sv_family_of_common_macro(&self, macro_name: InternedStr) -> Option<InternedStr> {
768 self.common_macro_to_sv_family.get(¯o_name).copied()
769 }
770
771 pub fn flexible_array_element(&self, struct_name: InternedStr, field_name: InternedStr)
777 -> Option<&TypeRepr>
778 {
779 if let Some(t) = self.flexible_array_fields.get(&(struct_name, field_name)) {
780 return Some(t);
781 }
782 let resolved = self.resolve_typedef(struct_name)?;
783 self.flexible_array_fields.get(&(resolved, field_name))
784 }
785
786 pub fn is_flexible_array_field(&self, struct_name: InternedStr, field_name: InternedStr) -> bool {
788 self.flexible_array_element(struct_name, field_name).is_some()
789 }
790
791 pub fn build_common_macro_sv_family(&mut self, interner: &StringInterner) {
799 let mut new_map: HashMap<InternedStr, InternedStr> = HashMap::new();
800 for (¯o_id, struct_names) in &self.common_macro_to_structs {
801 let mut sv_typedefs: HashSet<InternedStr> = HashSet::new();
802 for &xpv_struct in struct_names {
803 let xpv_typedef = match self.get_typedef_for_struct(xpv_struct) {
804 Some(td) => td,
805 None => continue,
806 };
807 let xpv_typedef_str = interner.get(xpv_typedef);
808 let sv_struct = match self.sv_head_type_to_struct.get(xpv_typedef_str) {
809 Some(&s) => s,
810 None => continue, };
812 if let Some(td) = self.get_typedef_for_struct(sv_struct) {
813 sv_typedefs.insert(td);
814 }
815 }
816 if sv_typedefs.len() == 1 {
817 new_map.insert(macro_id, *sv_typedefs.iter().next().unwrap());
818 }
819 }
820 self.common_macro_to_sv_family = new_map;
821 }
822
823 pub fn build_common_field_rust_types(
830 &mut self,
831 rust_dict: &crate::rust_decl::RustDeclDict,
832 interner: &mut StringInterner,
833 ) {
834 use std::collections::hash_map::Entry;
835 let target_names: HashSet<InternedStr> = self
837 .common_macros
838 .values()
839 .flat_map(|m| m.fields.iter().map(|f| f.name))
840 .collect();
841 if target_names.is_empty() {
842 return;
843 }
844
845 let mut acc: HashMap<InternedStr, String> = HashMap::new();
846 let mut conflicts: HashSet<InternedStr> = HashSet::new();
847
848 for rust_struct in rust_dict.structs.values() {
849 for field in &rust_struct.fields {
850 let id = interner.intern(&field.name);
851 if !target_names.contains(&id) {
852 continue;
853 }
854 if conflicts.contains(&id) {
855 continue;
856 }
857 match acc.entry(id) {
858 Entry::Vacant(e) => {
859 e.insert(field.ty.clone());
860 }
861 Entry::Occupied(e) => {
862 if e.get() != &field.ty {
863 conflicts.insert(id);
864 e.remove();
865 }
866 }
867 }
868 }
869 }
870
871 for (id, ty_str) in acc {
872 let repr = TypeRepr::RustType {
873 repr: crate::type_repr::RustTypeRepr::from_type_string(&ty_str),
874 source: crate::type_repr::RustTypeSource::Parsed { raw: ty_str },
875 };
876 self.common_field_rust_types.insert(id, repr);
877 }
878 }
879
880 pub fn build_common_macro_fields<F>(
890 &mut self,
891 macro_bodies: &[(InternedStr, Vec<crate::token::Token>)],
892 mut parse_struct_members: F,
893 ) where
894 F: FnMut(Vec<crate::token::Token>) -> Result<Vec<StructMember>, crate::error::CompileError>,
895 {
896 for (macro_name, body) in macro_bodies {
897 let members = match parse_struct_members(body.clone()) {
898 Ok(m) => m,
899 Err(_) => continue, };
901 let mut fields = Vec::new();
902 for member in &members {
903 Self::collect_common_fields_from_member(member, CommonFieldOrigin::Direct, &mut fields);
904 }
905 for f in &fields {
906 self.field_to_defining_macro.insert(f.name, *macro_name);
907 }
908 self.common_macros.insert(
909 *macro_name,
910 CommonFieldMacro { name: *macro_name, fields },
911 );
912 }
913 }
914
915 fn collect_common_fields_from_member(
917 member: &StructMember,
918 outer_origin: CommonFieldOrigin,
919 out: &mut Vec<CommonField>,
920 ) {
921 for decl in &member.declarators {
923 let Some(declarator) = decl.declarator.as_ref() else { continue };
924 let Some(field_name) = declarator.name else { continue };
925 let is_fn_pointer = is_fn_pointer_declarator(&declarator.derived);
926 out.push(CommonField {
927 name: field_name,
928 is_fn_pointer,
929 origin: outer_origin.clone(),
930 });
931
932 for type_spec in &member.specs.type_specs {
935 let nested = match type_spec {
936 TypeSpec::Struct(s) | TypeSpec::Union(s) => s,
937 _ => continue,
938 };
939 if nested.name.is_some() {
940 continue; }
942 let Some(inner_members) = &nested.members else { continue };
943 for inner in inner_members {
944 Self::collect_common_fields_from_member(
945 inner,
946 CommonFieldOrigin::InsideUnion { union_field: field_name },
947 out,
948 );
949 }
950 }
951 }
952 }
953
954 pub fn register_sv_u_field(&mut self, field_name: InternedStr, c_type: String) {
961 self.sv_u_field_types.insert(field_name, c_type);
962 }
963
964 pub fn get_sv_u_field_type(&self, field_name: InternedStr) -> Option<&str> {
969 self.sv_u_field_types.get(&field_name).map(|s| s.as_str())
970 }
971
972 pub fn sv_u_field_types_count(&self) -> usize {
974 self.sv_u_field_types.len()
975 }
976
977 pub fn build_consistent_type_cache(&mut self, interner: &StringInterner) {
984 self.consistent_type_cache.clear();
985
986 let field_structs: Vec<_> = self.field_to_structs.iter()
988 .map(|(&k, v)| (k, v.clone()))
989 .collect();
990
991 for (field_name, structs) in field_structs {
992 let consistent_type = self.compute_consistent_type(field_name, &structs, interner);
993 self.consistent_type_cache.insert(field_name, consistent_type);
994 }
995 }
996
997 fn compute_consistent_type(
1002 &self,
1003 field_name: InternedStr,
1004 structs: &HashSet<InternedStr>,
1005 interner: &StringInterner,
1006 ) -> Option<TypeRepr> {
1007 if structs.is_empty() {
1008 return None;
1009 }
1010
1011 let mut first_type: Option<(&TypeRepr, String)> = None;
1012
1013 for struct_name in structs {
1014 if let Some(ft) = self.field_types.get(&(*struct_name, field_name)) {
1015 let type_str = ft.type_repr.to_rust_string(interner);
1016 match &first_type {
1017 None => first_type = Some((&ft.type_repr, type_str)),
1018 Some((_, first_str)) if first_str != &type_str => return None, Some(_) => {} }
1021 }
1022 }
1023
1024 first_type.map(|(tr, _)| tr.clone())
1025 }
1026
1027 pub fn get_consistent_field_type(&self, field_name: InternedStr) -> Option<&TypeRepr> {
1032 self.consistent_type_cache
1033 .get(&field_name)
1034 .and_then(|opt| opt.as_ref())
1035 }
1036
1037 pub fn dump(&self, interner: &StringInterner) -> String {
1041 let mut result = String::new();
1042
1043 let mut entries: Vec<_> = self.field_to_structs.iter().collect();
1045 entries.sort_by_key(|(field, _)| interner.get(**field));
1046
1047 for (field_name, struct_names) in entries {
1048 let field_str = interner.get(*field_name);
1049
1050 let mut struct_strs: Vec<_> = struct_names
1052 .iter()
1053 .map(|s| interner.get(*s))
1054 .collect();
1055 struct_strs.sort();
1056
1057 result.push_str(&format!(
1058 "{} -> {}\n",
1059 field_str,
1060 struct_strs.join(", ")
1061 ));
1062 }
1063
1064 result
1065 }
1066
1067 pub fn dump_unique(&self, interner: &StringInterner) -> String {
1069 let mut result = String::new();
1070
1071 let mut entries: Vec<_> = self.field_to_structs
1073 .iter()
1074 .filter(|(_, structs)| structs.len() == 1)
1075 .collect();
1076 entries.sort_by_key(|(field, _)| interner.get(**field));
1077
1078 for (field_name, struct_names) in entries {
1079 let field_str = interner.get(*field_name);
1080 let struct_str = interner.get(*struct_names.iter().next().unwrap());
1081 result.push_str(&format!("{} -> {}\n", field_str, struct_str));
1082 }
1083
1084 result
1085 }
1086
1087 pub fn stats(&self) -> FieldsDictStats {
1089 let total_fields = self.field_to_structs.len();
1090 let unique_fields = self.field_to_structs
1091 .values()
1092 .filter(|s| s.len() == 1)
1093 .count();
1094 let ambiguous_fields = total_fields - unique_fields;
1095
1096 FieldsDictStats {
1097 total_fields,
1098 unique_fields,
1099 ambiguous_fields,
1100 }
1101 }
1102
1103 pub fn dump_field_types(&self, interner: &StringInterner) -> String {
1105 let mut result = String::new();
1106
1107 let mut entries: Vec<_> = self.field_types.iter().collect();
1109 entries.sort_by_key(|((struct_name, field_name), _)| {
1110 (interner.get(*struct_name), interner.get(*field_name))
1111 });
1112
1113 for ((struct_name, field_name), field_type) in entries {
1114 let struct_str = interner.get(*struct_name);
1115 let field_str = interner.get(*field_name);
1116 let type_str = field_type.type_repr.to_rust_string(interner);
1117 result.push_str(&format!(
1118 "{}.{}: {}\n",
1119 struct_str, field_str, type_str
1120 ));
1121 }
1122
1123 result
1124 }
1125
1126 pub fn dump_typedefs(&self, interner: &StringInterner) -> String {
1128 let mut result = String::new();
1129
1130 let mut entries: Vec<_> = self.typedef_to_struct.iter().collect();
1132 entries.sort_by_key(|(typedef_name, _)| interner.get(**typedef_name));
1133
1134 for (typedef_name, struct_name) in entries {
1135 let typedef_str = interner.get(*typedef_name);
1136 let struct_str = interner.get(*struct_name);
1137 result.push_str(&format!("typedef {} = struct {}\n", typedef_str, struct_str));
1138 }
1139
1140 result
1141 }
1142}
1143
1144#[derive(Debug)]
1146pub struct FieldsDictStats {
1147 pub total_fields: usize,
1148 pub unique_fields: usize,
1149 pub ambiguous_fields: usize,
1150}
1151
1152#[cfg(test)]
1153mod tests {
1154 use super::*;
1155
1156 #[test]
1157 fn test_fields_dict() {
1158 }
1160}