"""Conservative parser for top-level Config metadata object identity.""" from __future__ import annotations from dataclasses import asdict, dataclass from pathlib import Path from typing import Any from .payload import GUID_RE, parse_payload_file, root_signature, scalar @dataclass(frozen=True) class MetadataObjectIdentity: guid: str name: str synonyms: dict[str, str] evidence_path: str def to_dict(self) -> dict[str, Any]: return asdict(self) def _is_guid(value: str) -> bool: return bool(GUID_RE.fullmatch(value)) def _identity_guid(node: Any) -> str: if not (isinstance(node, dict) and node.get("type") == "list"): return "" items = node.get("items") or [] if len(items) != 3: return "" if scalar(items[0]) != "1" or scalar(items[1]) != "0": return "" guid = scalar(items[2]).lower() return guid if _is_guid(guid) else "" def _synonyms(node: Any) -> dict[str, str]: if not (isinstance(node, dict) and node.get("type") == "list"): return {} items = node.get("items") or [] if not items: return {} try: declared_count = int(scalar(items[0])) except ValueError: return {} if declared_count < 0 or len(items) < 1 + declared_count * 2: return {} result = {} index = 1 end = 1 + declared_count * 2 while index + 1 < end: language = scalar(items[index]) value = scalar(items[index + 1]) if language and value: result[language] = value index += 2 return result def find_identity(tree: Any) -> MetadataObjectIdentity | None: """Find the observed object identity block in a generic brace tree.""" def walk(node: Any, path: list[int]) -> MetadataObjectIdentity | None: if isinstance(node, dict) and node.get("type") == "list": items = node.get("items") or [] for index in range(0, max(len(items) - 2, 0)): guid = _identity_guid(items[index]) name = scalar(items[index + 1]) synonym_node = items[index + 2] synonym_items = synonym_node.get("items") if isinstance(synonym_node, dict) and synonym_node.get("type") == "list" else None try: synonym_count = int(scalar(synonym_items[0])) if synonym_items else -1 except ValueError: synonym_count = -1 synonyms = _synonyms(synonym_node) if guid and name and synonym_count >= 0 and len(synonym_items or []) >= 1 + synonym_count * 2: return MetadataObjectIdentity( guid=guid, name=name, synonyms=synonyms, evidence_path=".".join(str(part) for part in [*path, index]), ) for child_index, child in enumerate(items): found = walk(child, [*path, child_index]) if found: return found return None return walk(tree, []) def parse_config_object_file(path: Path) -> dict[str, Any]: payload = parse_payload_file(path) tree = payload.get("tree") identity = find_identity(tree) return { "source_path": str(path), "compression": payload.get("compression"), "encoding": payload.get("encoding"), "raw_bytes": payload.get("raw_bytes"), "payload_bytes": payload.get("payload_bytes"), "root": root_signature(tree), "identity": identity.to_dict() if identity else None, "tree": tree, }