Skip to main content

libxml_rs/abi/
structs.rs

1// Lint policy (11.1-Z seal): `missing_docs` and
2// `missing_debug_implementations` are allowed here — the fields mirror
3// upstream C structs whose canonical documentation is the C header itself
4// (the same rationale bindgen applies to generated bindings). The exported
5// `#[repr(C)]` layout is the contract, verified byte-for-byte by the
6// data-abi courts; the Rust doc surface adds nothing to it.
7#![allow(missing_docs, missing_debug_implementations)]
8
9//! C ABI struct definitions — exact upstream layout (§14, §17).
10//!
11//! Every struct in this module is laid out to match the corresponding
12//! upstream C struct byte-for-byte on the target platform.
13//!
14//! # Upstream structs
15//!
16//! All structs derived from SRC-LIBXML2-2.15.3-TREE-H and related headers.
17//! See the sub-agent extraction output for complete field-level archaeology.
18//!
19//! # Safety
20//!
21//! These structs are `#[repr(C)]` and may be passed across the FFI boundary.
22//! Fields marked `_deprecated_*` or `_unused_*` are retained for ABI
23//! compatibility even when the upstream has deprecated them.
24//!
25//! # Phase 1 status
26//!
27//! All core tree structs, error struct, parser context, SAX handler,
28//! XPath context/object, and I/O structs are defined.
29//!
30//! # ABI verification
31//!
32//! Each struct must be verified with `offsetof`/`sizeof` probes compiled
33//! from upstream headers. See courts/abi-struct-*.json for receipts.
34//!
35//! # Upstream contract
36//!
37//! Every `#[repr(C)]` mirror is field-for-field identical to the upstream C
38//! headers at the 2.15.3/1.1.45 parity target: `tree.h`, `parser.h`, `xpath.h`,
39//! `SAX2.h`, `encoding.h`, `xslt.h`, `schemasInternals.h` and friends
40//! (SRC-LIBXML2 / SRC-LIBXSLT archaeology trees). The header closure in
41//! `include/` was extracted verbatim by `tools/headers/header_closure.py`
42//! (R-000124) and the Rust mirrors are measured against those headers.
43//!
44//! # Conceptual behavior
45//!
46//! This module implements the C-visible struct layout surface: tree nodes,
47//! documents, parser contexts, SAX handlers, XPath contexts/objects, buffers,
48//! error structs, encoding handlers, and the libxslt engine structs. The
49//! layout IS the behavior — a C consumer reads these fields at fixed offsets,
50//! so size and field order are ABI contract, verified by offsetof/sizeof
51//! probes.
52//!
53//! # Ownership & safety invariants
54//!
55//! These structs are raw C-layout data; ownership of the pointed-to children
56//! follows OWNERSHIP_ATLAS (borrowed parent/doc/ns pointers, owned children
57//! lists). Fields marked deprecated or unused are retained for ABI
58//! compatibility. The mirrors are `unsafe` to construct/destroy because the C
59//! header layout is the invariant and Rust must not add layout assumptions.
60//!
61//! # Historical quirks & epochs
62//!
63//! R-000139 (11.1-I): the Rust `_xmlElement` was 56 bytes vs the headers 104
64//! — every `xmlMalloc(sizeof(_xmlElement))` was 48 bytes short. R-000140:
65//! eight libxslt mirrors diverged (121 mismatches, e.g. `_xsltTemplate`
66//! missing the match field entirely) until rewritten from clang record-layout
67//! dumps; the XSLT_REFACTORED-gated fields are omitted because the oracle DSO
68//! ships with XSLT_REFACTORED disabled. R-000129: `_xmlCharEncodingHandler`
69//! was 48 bytes vs upstream 56. R-000135 added the `_xmlSAXHandlerV1` /
70//! `xmlChRangeGroup` mirrors.
71//!
72//! # Deliberate oddities
73//!
74//! Missing-docs and missing-debug-implementations are allowed here
75//! deliberately: the C headers are the canonical documentation (bindgen
76//! rationale), and the byte-exact layout is the contract. Opaque types (dict,
77//! hash, list, regexp, automata, catalog) are defined as empty handles on
78//! purpose — upstream keeps them opaque in the headers too.
79//!
80//! # Proving courts
81//!
82//! The RUST-MIRROR-ABI court (`tools/abi/rust_mirror_abi.py`) measures every
83//! mirror against clang -fdump-record-layouts output of the candidate headers
84//! (0 mismatches at the 11.1-I seal); the C ABI courts compile offsetof/sizeof
85//! probes against the upstream headers; the DATA-GLOBALS-001 and CALLBACK-001
86//! probes exercise the SAX/error structs at runtime.
87//!
88//! # Tempting simplifications that would break parity
89//!
90//! A tempting simplification is to rewrite the mirrors as ergonomic Rust
91//! structs (Options, Vecs, enums with payloads) — that is precisely the
92//! defect R-000139/R-000140 fixed and it would shift every field offset a C
93//! consumer reads. Another tempting shortcut is to drop the deprecated fields:
94//! upstream retains them in the ABI, so a smaller struct would make `sizeof`
95//! and every downstream allocation wrong. The mirrors must not diverge from
96//! the headers even when a field is never used by the candidate.
97
98use crate::abi::callbacks::*;
99use crate::abi::types::*;
100use std::os::raw::{c_char, c_int, c_long, c_uint, c_ulong, c_ushort, c_void};
101
102// ── Forward declarations ────────────────────────────────────────────────
103//
104// These are the internal struct tags. In C, these are typedef'd to
105// pointer types. We define them as opaque handles or full structs
106// depending on whether the struct is public or opaque.
107
108// Opaque types (defined in .c files, not exposed in headers):
109//   _xmlDict, _xmlHashTable, _xmlList, _xmlRegexp, _xmlCatalog,
110//   _xmlXPathCompExpr, _xmlAutomata, _xmlPattern
111
112// ── xmlBuffer ───────────────────────────────────────────────────────────
113//
114// Source: tree.h lines 109-126
115
116/// Buffer structure. Deprecated in favor of xmlBuf.
117#[repr(C)]
118pub struct _xmlBuffer {
119    pub content: *mut xmlChar,   // The buffer content UTF8 (deprecated)
120    pub use_: c_uint,            // The buffer size used (deprecated)
121    pub size: c_uint,            // The buffer size (deprecated)
122    pub alloc: c_int,            // The realloc method (deprecated)
123    pub contentIO: *mut xmlChar, // In IO mode may have different base (deprecated)
124}
125
126// ── xmlNotation ─────────────────────────────────────────────────────────
127//
128// Source: tree.h lines 297-305
129
130/// Notation declaration.
131#[repr(C)]
132pub struct _xmlNotation {
133    pub name: *const xmlChar,     // Notation name
134    pub PublicID: *const xmlChar, // Public identifier, if any
135    pub SystemID: *const xmlChar, // System identifier, if any
136}
137
138// ── xmlEnumeration ──────────────────────────────────────────────────────
139//
140// Source: tree.h lines 341-345
141
142/// Enumeration value for attribute declarations.
143#[repr(C)]
144pub struct _xmlEnumeration {
145    pub next: *mut _xmlEnumeration, // Next in enumeration (deprecated)
146    pub name: *const xmlChar,       // Enumeration value
147}
148
149// ── xmlAttribute (declaration) ──────────────────────────────────────────
150//
151// Source: tree.h lines 357-391
152// NOTE: This is the ATTRIBUTE DECLARATION struct, not attribute node.
153// Attribute node is _xmlAttr below.
154
155/// Attribute declaration from DTD.
156#[repr(C)]
157pub struct _xmlAttribute {
158    pub _private: *mut c_void,   // Application data
159    pub type_: c_int,            // XML_ATTRIBUTE_DECL
160    pub name: *const xmlChar,    // Attribute name
161    pub children: *mut _xmlNode, // NULL
162    pub last: *mut _xmlNode,     // NULL
163    pub parent: *mut _xmlDtd,    // DTD
164    pub next: *mut _xmlNode,     // Next sibling
165    pub prev: *mut _xmlNode,     // Previous sibling
166    pub doc: *mut _xmlDoc,       // Containing document
167
168    pub nexth: *mut _xmlAttribute,  // Next in hash table
169    pub atype: c_int,               // Attribute type
170    pub def: c_int,                 // Attribute default
171    pub defaultValue: *mut xmlChar, // Default value
172    pub tree: *mut _xmlEnumeration, // Enumeration tree (deprecated)
173    pub prefix: *const xmlChar,     // Namespace prefix
174    pub elem: *const xmlChar,       // Element name
175}
176
177// ── xmlElementContent ───────────────────────────────────────────────────
178//
179// Source: tree.h lines 423-438
180
181/// Element content model.
182#[repr(C)]
183pub struct _xmlElementContent {
184    pub type_: c_int,                    // PCDATA, ELEMENT, SEQ or OR (deprecated)
185    pub ocur: c_int,                     // ONCE, OPT, MULT or PLUS (deprecated)
186    pub name: *const xmlChar,            // Element name (deprecated)
187    pub c1: *mut _xmlElementContent,     // First child (deprecated)
188    pub c2: *mut _xmlElementContent,     // Second child (deprecated)
189    pub parent: *mut _xmlElementContent, // Parent (deprecated)
190    pub prefix: *const xmlChar,          // Namespace prefix (deprecated)
191}
192
193// ── xmlElement (declaration) ────────────────────────────────────────────
194//
195// Source: tree.h lines 447-474
196
197/// Element declaration from DTD.
198///
199/// # ABI
200///
201/// Layout mirrors upstream `struct _xmlElement` (libxml2 2.15.x tree.h): the
202/// declaration is node-shaped (children/last/parent/next/prev/doc) even though
203/// it is stored in the DTD's element hash table. `cont_model` is the compiled
204/// content-model regexp built by `xmlValidBuildContentModel` and is opaque
205/// here (`xmlRegexp *` upstream).
206#[repr(C)]
207pub struct _xmlElement {
208    pub _private: *mut c_void,            // application data
209    pub type_: c_int,                     // xmlElementType (XML_ELEMENT_DECL)
210    pub name: *const xmlChar,             // Element name
211    pub children: *mut _xmlNode,          // NULL
212    pub last: *mut _xmlNode,              // NULL
213    pub parent: *mut _xmlDtd,             // -> DTD
214    pub next: *mut _xmlNode,              // next sibling (NULL for decls)
215    pub prev: *mut _xmlNode,              // previous sibling (NULL for decls)
216    pub doc: *mut _xmlDoc,                // containing document
217    pub etype: c_int,                     // xmlElementTypeVal
218    pub content: *mut _xmlElementContent, // Content model
219    pub attributes: *mut _xmlAttribute,   // List of declared attributes
220    pub prefix: *const xmlChar,           // Namespace prefix
221    pub cont_model: *mut c_void,          // validating regexp (xmlRegexp *)
222}
223
224// ── xmlNs ───────────────────────────────────────────────────────────────
225//
226// Source: tree.h lines 501-512
227
228/// Namespace declaration or XPath namespace node.
229#[repr(C)]
230pub struct _xmlNs {
231    pub next: *mut _xmlNs,      // Next namespace
232    pub type_: c_int,           // XML_NAMESPACE_DECL
233    pub href: *const xmlChar,   // Namespace URI
234    pub prefix: *const xmlChar, // Namespace prefix
235    pub _private: *mut c_void,  // Application data
236    pub context: *mut _xmlDoc,  // Normally an xmlDoc (deprecated)
237}
238
239// ── xmlDtd ──────────────────────────────────────────────────────────────
240//
241// Source: tree.h lines 538-564
242
243/// DTD (Document Type Definition).
244#[repr(C)]
245pub struct _xmlDtd {
246    pub _private: *mut c_void,   // Application data
247    pub type_: c_int,            // XML_DTD_NODE
248    pub name: *const xmlChar,    // Name of the DTD
249    pub children: *mut _xmlNode, // First child
250    pub last: *mut _xmlNode,     // Last child
251    pub parent: *mut _xmlDoc,    // Parent node (document)
252    pub next: *mut _xmlNode,     // Next sibling
253    pub prev: *mut _xmlNode,     // Previous sibling
254    pub doc: *mut _xmlDoc,       // Containing document
255    // End of common part
256    pub notations: *mut c_void,   // Hash table for notations
257    pub elements: *mut c_void,    // Hash table for elements
258    pub attributes: *mut c_void,  // Hash table for attributes
259    pub entities: *mut c_void,    // Hash table for entities
260    pub ExternalID: *mut xmlChar, // Public identifier
261    pub SystemID: *mut xmlChar,   // System identifier
262    pub pentities: *mut c_void,   // Hash table for parameter entities
263}
264
265// ── xmlAttr ─────────────────────────────────────────────────────────────
266//
267// Source: tree.h lines 595-615
268
269/// Attribute node.
270#[repr(C)]
271pub struct _xmlAttr {
272    pub _private: *mut c_void,   // Application data
273    pub type_: c_int,            // XML_ATTRIBUTE_NODE
274    pub name: *const xmlChar,    // Local name
275    pub children: *mut _xmlNode, // First child (text value)
276    pub last: *mut _xmlNode,     // Last child
277    pub parent: *mut _xmlNode,   // Parent node
278    pub next: *mut _xmlAttr,     // Next sibling (attribute)
279    pub prev: *mut _xmlAttr,     // Previous sibling (attribute)
280    pub doc: *mut _xmlDoc,       // Containing document
281    pub ns: *mut _xmlNs,         // Namespace if any
282    pub atype: c_int,            // Attribute type
283    pub psvi: *mut c_void,       // Type/PSVI information
284    pub id: *mut c_void,         // ID struct (deprecated)
285}
286
287// ── xmlNode ─────────────────────────────────────────────────────────────
288//
289// Source: tree.h lines 645-688
290
291/// XML node — the core tree structure.
292#[repr(C)]
293pub struct _xmlNode {
294    pub _private: *mut c_void,   // Application data
295    pub type_: c_int,            // Type enum
296    pub name: *const xmlChar,    // Node name
297    pub children: *mut _xmlNode, // First child
298    pub last: *mut _xmlNode,     // Last child
299    pub parent: *mut _xmlNode,   // Parent node (NULL for documents)
300    pub next: *mut _xmlNode,     // Next sibling
301    pub prev: *mut _xmlNode,     // Previous sibling
302    pub doc: *mut _xmlDoc,       // Associated document
303    // End of common part
304    pub ns: *mut _xmlNs,           // Namespace of element
305    pub content: *mut xmlChar,     // Content (text/comment/PI)
306    pub properties: *mut _xmlAttr, // First attribute of element
307    pub nsDef: *mut _xmlNs,        // First namespace definition
308    pub psvi: *mut c_void,         // Type/PSVI information
309    pub line: c_ushort,            // Line number
310    pub extra: c_ushort,           // Extra data for XPath/XSLT
311}
312
313// ── xmlDoc ──────────────────────────────────────────────────────────────
314//
315// Source: tree.h lines 787-845
316
317/// XML Document.
318#[repr(C)]
319pub struct _xmlDoc {
320    pub _private: *mut c_void,   // Application data
321    pub type_: c_int,            // XML_DOCUMENT_NODE or XML_HTML_DOCUMENT_NODE
322    pub name: *mut c_char,       // NULL
323    pub children: *mut _xmlNode, // First child (root element)
324    pub last: *mut _xmlNode,     // Last child
325    pub parent: *mut _xmlNode,   // Parent node
326    pub next: *mut _xmlNode,     // Next sibling
327    pub prev: *mut _xmlNode,     // Previous sibling
328    pub doc: *mut _xmlDoc,       // Reference to itself
329    // End of common part
330    pub compression: c_int,      // Level of zlib compression
331    pub standalone: c_int,       // Standalone document status
332    pub intSubset: *mut _xmlDtd, // Internal subset
333    pub extSubset: *mut _xmlDtd, // External subset
334    pub oldNs: *mut _xmlNs,      // Old namespace (used during parsing)
335    pub version: *mut xmlChar,   // Version string from XML declaration
336    pub encoding: *mut xmlChar,  // Actual encoding
337    pub ids: *mut c_void,        // Hash table for ID attributes
338    pub refs: *mut c_void,       // Hash table for IDREFs (deprecated)
339    pub URL: *mut xmlChar,       // URI of the document
340    pub charset: c_int,          // Unused (encoding indicator)
341    pub dict: *mut c_void,       // Dictionary for names (opaque _xmlDict)
342    pub psvi: *mut c_void,       // Type/PSVI information
343    pub parseFlags: c_int,       // Parser options used
344    pub properties: c_int,       // Document properties flags
345}
346
347// ── xmlEntity ───────────────────────────────────────────────────────────
348//
349// Source: entities.h lines 42-74
350
351/// Entity declaration.
352#[repr(C)]
353pub struct _xmlEntity {
354    pub _private: *mut c_void,      // Application data
355    pub type_: c_int,               // XML_ENTITY_DECL (must be second!)
356    pub name: *const xmlChar,       // Entity name
357    pub children: *mut _xmlNode,    // First child link
358    pub last: *mut _xmlNode,        // Last child link
359    pub parent: *mut _xmlDtd,       // -> DTD
360    pub next: *mut _xmlNode,        // Next sibling link
361    pub prev: *mut _xmlNode,        // Previous sibling link
362    pub doc: *mut _xmlDoc,          // The containing document
363    pub orig: *mut xmlChar,         // Content without ref substitution
364    pub content: *mut xmlChar,      // Content or ndata if unparsed
365    pub length: c_int,              // The content length
366    pub etype: c_int,               // The entity type
367    pub ExternalID: *const xmlChar, // External identifier for PUBLIC
368    pub SystemID: *const xmlChar,   // URI for SYSTEM or PUBLIC Entity
369    pub nexte: *mut _xmlEntity,     // Unused
370    pub URI: *const xmlChar,        // The full URI as computed
371    pub owner: c_int,               // Unused
372    pub flags: c_int,               // Various flags
373    pub expandedSize: c_ulong,      // Expanded size
374}
375
376// ── xmlError ────────────────────────────────────────────────────────────
377//
378// Source: xmlerror.h
379
380/// Structured error information.
381#[repr(C)]
382#[derive(Debug)]
383pub struct _xmlError {
384    pub domain: c_int,        // Error domain
385    pub code: c_int,          // Error code
386    pub message: *mut c_char, // Human-readable error message
387    pub level: c_int,         // Error level
388    pub file: *mut c_char,    // Filename if available
389    pub line: c_int,          // Line number if available
390    pub str1: *mut c_char,    // Extra string information
391    pub str2: *mut c_char,    // Extra string information
392    pub str3: *mut c_char,    // Extra string information
393    pub int1: c_int,          // Extra number information
394    pub int2: c_int,          // Column number if available
395    pub ctxt: *mut c_void,    // Parser context if available
396    pub node: *mut c_void,    // Node if available
397}
398
399// ── xmlParserInput ──────────────────────────────────────────────────────
400//
401// Source: parser.h
402
403/// Parser input stream.
404#[repr(C)]
405pub struct _xmlParserInput {
406    pub buf: *mut _xmlParserInputBuffer, // Input buffer (deprecated)
407    pub filename: *const c_char,         // The filename or URI (deprecated)
408    pub directory: *const c_char,        // Unused (deprecated)
409    pub base: *const xmlChar,            // Base of the array to parse
410    pub cur: *const xmlChar,             // Current char being parsed (deprecated)
411    pub end: *const xmlChar,             // End of the array to parse
412    pub length: c_int,                   // Unused (deprecated)
413    pub line: c_int,                     // Current line (deprecated)
414    pub col: c_int,                      // Current column (deprecated)
415    pub consumed: c_ulong,               // How many xmlChars consumed (deprecated)
416    pub free: Option<unsafe extern "C" fn(*mut c_char)>, // Deallocation func (deprecated)
417    pub encoding: *const xmlChar,        // Unused (deprecated)
418    pub version: *const xmlChar,         // The version string for entity (deprecated)
419    pub flags: c_int,                    // Flags (deprecated)
420    pub id: c_int,                       // Unique identifier (deprecated)
421    pub parentConsumed: c_ulong,         // Unused (deprecated)
422    pub entity: *mut _xmlEntity,         // Entity if any (deprecated)
423}
424
425// ── xmlParserInputBuffer ────────────────────────────────────────────────
426//
427// Source: xmlIO.h
428
429/// Parser input buffer.
430#[repr(C)]
431pub struct _xmlParserInputBuffer {
432    pub context: *mut c_void,                         // (deprecated)
433    pub readcallback: Option<xmlInputReadCallback>,   // (deprecated)
434    pub closecallback: Option<xmlInputCloseCallback>, // (deprecated)
435    pub encoder: *mut c_void,                         // I18N converter (deprecated)
436    pub buffer: *mut c_void,                          // Local buffer (deprecated)
437    pub raw: *mut c_void,                             // Raw input buffer (deprecated)
438    pub compressed: c_int,                            // Compression flag (deprecated)
439    pub error: c_int,                                 // (deprecated)
440    pub rawconsumed: c_ulong,                         // (deprecated)
441}
442
443// ── xmlOutputBuffer ─────────────────────────────────────────────────────
444//
445// Source: xmlIO.h
446
447/// Output buffer.
448#[repr(C)]
449pub struct _xmlOutputBuffer {
450    pub context: *mut c_void,                          // (deprecated)
451    pub writecallback: Option<xmlOutputWriteCallback>, // (deprecated)
452    pub closecallback: Option<xmlOutputCloseCallback>, // (deprecated)
453    pub encoder: *mut c_void,                          // I18N converter
454    pub buffer: *mut c_void,                           // Local buffer
455    pub conv: *mut c_void,                             // Output conversion buffer
456    pub written: c_int,                                // Total bytes written
457    pub error: c_int,                                  // Error flag
458}
459
460// ── xmlCharEncodingHandler ───────────────────────────────────────────────
461//
462// Source: encoding.h
463
464/// Character encoding conversion handler.
465///
466/// # UPSTREAM-PARITY
467///
468/// Layout matches upstream `encoding.h` `struct _xmlCharEncodingHandler`
469/// (2.15.x): `name`, then two anonymous unions (`input`, `output`) each
470/// carrying either a modern `xmlCharEncConvFunc` or a legacy
471/// `xmlCharEncodingInputFunc`/`xmlCharEncodingOutputFunc`, then
472/// `inputCtxt`, `outputCtxt`, `ctxtDtor`, `flags`.
473/// sizeof == 56, _Alignof == 8 on x86-64.
474#[repr(C)]
475pub union EncodingInputUnion {
476    pub func: Option<xmlCharEncConvFunc>,
477    pub legacyFunc: Option<xmlCharEncodingInputFunc>,
478}
479
480/// Output-side counterpart of [`EncodingInputUnion`].
481#[repr(C)]
482pub union EncodingOutputUnion {
483    pub func: Option<xmlCharEncConvFunc>,
484    pub legacyFunc: Option<xmlCharEncodingOutputFunc>,
485}
486
487/// Character encoding conversion handler.
488#[repr(C)]
489pub struct _xmlCharEncodingHandler {
490    pub name: *mut c_char,                        // Encoding name
491    pub input: EncodingInputUnion,                // Input converter (union)
492    pub output: EncodingOutputUnion,              // Output converter (union)
493    pub inputCtxt: *mut c_void,                   // Iconv context for input
494    pub outputCtxt: *mut c_void,                  // Iconv context for output
495    pub ctxtDtor: Option<xmlCharEncConvCtxtDtor>, // Context destructor
496    pub flags: c_int,                             // xmlCharEncFlags
497}
498
499// ── xmlBuf ──────────────────────────────────────────────────────────────
500//
501// Source: tree.h
502
503/// Buffer structure (modern replacement for xmlBuffer).
504#[repr(C)]
505pub struct _xmlBuf {
506    pub content: *mut xmlChar, // The buffer content UTF8
507    pub use_: c_uint,          // The buffer size used
508    pub size: c_uint,          // The buffer size
509    pub alloc: c_int,          // The realloc method
510    pub error: c_int,          // Error flag
511    pub buffer: c_int,         // Is this a buffer from xmlBuffer?
512    pub io: c_int,             // In IO mode?
513}
514
515// ── xmlSAXHandler ───────────────────────────────────────────────────────
516//
517// Source: parser.h
518
519/// SAX event handler structure.
520#[repr(C)]
521pub struct _xmlSAXHandler {
522    pub internalSubset: Option<internalSubsetSAXFunc>,
523    pub isStandalone: Option<isStandaloneSAXFunc>,
524    pub hasInternalSubset: Option<hasInternalSubsetSAXFunc>,
525    pub hasExternalSubset: Option<hasExternalSubsetSAXFunc>,
526    pub resolveEntity: Option<resolveEntitySAXFunc>,
527    pub getEntity: Option<getEntitySAXFunc>,
528    pub entityDecl: Option<entityDeclSAXFunc>,
529    pub notationDecl: Option<notationDeclSAXFunc>,
530    pub attributeDecl: Option<attributeDeclSAXFunc>,
531    pub elementDecl: Option<elementDeclSAXFunc>,
532    pub unparsedEntityDecl: Option<unparsedEntityDeclSAXFunc>,
533    pub setDocumentLocator: Option<setDocumentLocatorSAXFunc>,
534    pub startDocument: Option<startDocumentSAXFunc>,
535    pub endDocument: Option<endDocumentSAXFunc>,
536    pub startElement: Option<startElementSAXFunc>,
537    pub endElement: Option<endElementSAXFunc>,
538    pub reference: Option<referenceSAXFunc>,
539    pub characters: Option<charactersSAXFunc>,
540    pub ignorableWhitespace: Option<ignorableWhitespaceSAXFunc>,
541    pub processingInstruction: Option<processingInstructionSAXFunc>,
542    pub comment: Option<commentSAXFunc>,
543    pub warning: Option<warningSAXFunc>,
544    pub error: Option<errorSAXFunc>,
545    pub fatalError: Option<fatalErrorSAXFunc>,
546    pub getParameterEntity: Option<getParameterEntitySAXFunc>,
547    pub cdataBlock: Option<cdataBlockSAXFunc>,
548    pub externalSubset: Option<externalSubsetSAXFunc>,
549    pub initialized: c_uint,
550    pub _private: *mut c_void,
551    pub startElementNs: Option<startElementNsSAX2Func>,
552    pub endElementNs: Option<endElementNsSAX2Func>,
553    pub serror: Option<xmlStructuredErrorFunc>,
554}
555
556/// SAX handler, version 1 (upstream `struct _xmlSAXHandlerV1`, parser.h).
557///
558/// # ABI
559///
560/// Exactly the first 28 fields of `_xmlSAXHandler`; this is the type of the
561/// deprecated exported consts `xmlDefaultSAXHandler` / `htmlDefaultSAXHandler`.
562#[repr(C)]
563pub struct _xmlSAXHandlerV1 {
564    pub internalSubset: Option<internalSubsetSAXFunc>,
565    pub isStandalone: Option<isStandaloneSAXFunc>,
566    pub hasInternalSubset: Option<hasInternalSubsetSAXFunc>,
567    pub hasExternalSubset: Option<hasExternalSubsetSAXFunc>,
568    pub resolveEntity: Option<resolveEntitySAXFunc>,
569    pub getEntity: Option<getEntitySAXFunc>,
570    pub entityDecl: Option<entityDeclSAXFunc>,
571    pub notationDecl: Option<notationDeclSAXFunc>,
572    pub attributeDecl: Option<attributeDeclSAXFunc>,
573    pub elementDecl: Option<elementDeclSAXFunc>,
574    pub unparsedEntityDecl: Option<unparsedEntityDeclSAXFunc>,
575    pub setDocumentLocator: Option<setDocumentLocatorSAXFunc>,
576    pub startDocument: Option<startDocumentSAXFunc>,
577    pub endDocument: Option<endDocumentSAXFunc>,
578    pub startElement: Option<startElementSAXFunc>,
579    pub endElement: Option<endElementSAXFunc>,
580    pub reference: Option<referenceSAXFunc>,
581    pub characters: Option<charactersSAXFunc>,
582    pub ignorableWhitespace: Option<ignorableWhitespaceSAXFunc>,
583    pub processingInstruction: Option<processingInstructionSAXFunc>,
584    pub comment: Option<commentSAXFunc>,
585    pub warning: Option<warningSAXFunc>,
586    pub error: Option<errorSAXFunc>,
587    pub fatalError: Option<fatalErrorSAXFunc>,
588    pub getParameterEntity: Option<getParameterEntitySAXFunc>,
589    pub cdataBlock: Option<cdataBlockSAXFunc>,
590    pub externalSubset: Option<externalSubsetSAXFunc>,
591    pub initialized: c_uint,
592}
593
594/// Character-range table entry (upstream `xmlChSRange`, chvalid.h).
595#[repr(C)]
596pub struct xmlChSRange {
597    pub low: c_ushort,
598    pub high: c_ushort,
599}
600
601/// Long character-range table entry (upstream `xmlChLRange`, chvalid.h).
602#[repr(C)]
603pub struct xmlChLRange {
604    pub low: c_uint,
605    pub high: c_uint,
606}
607
608/// Character-class range group (upstream `xmlChRangeGroup`, chvalid.h) — the
609/// type of the exported char-class tables `xmlIsBaseCharGroup` &c.
610#[repr(C)]
611pub struct xmlChRangeGroup {
612    pub nbShortRange: c_int,
613    pub nbLongRange: c_int,
614    pub shortRange: *const xmlChSRange,
615    pub longRange: *const xmlChLRange,
616}
617
618// SAFETY: the group's raw pointers reference immutable `#[no_mangle]` const
619// arrays (generated from upstream data); they are never mutated, so the type
620// is safe to share across threads — required for the exported `static` tables
621// (upstream declares them `const`).
622unsafe impl Sync for xmlChRangeGroup {}
623
624// ── xmlParserCtxt ───────────────────────────────────────────────────────
625//
626// Source: parser.h
627
628/// Parser context — the primary parsing state structure.
629#[repr(C)]
630pub struct _xmlParserCtxt {
631    pub sax: *mut _xmlSAXHandler, // SAX handler (deprecated)
632    pub userData: *mut c_void,    // User data (deprecated)
633    pub myDoc: *mut _xmlDoc,      // Document being built (deprecated)
634    pub wellFormed: c_int,        // Is document well formed? (deprecated)
635    pub replaceEntities: c_int,   // Replace entities? (deprecated)
636    pub version: *mut xmlChar,    // XML version string (deprecated)
637    pub encoding: *mut xmlChar,   // Declared encoding (deprecated)
638    pub standalone: c_int,        // Standalone document (deprecated)
639    pub html: c_int,              // HTML document (deprecated)
640    // Input stream stack
641    pub input: *mut _xmlParserInput,         // Current input stream
642    pub inputNr: c_int,                      // Number of current input streams
643    pub inputMax: c_int,                     // Max number of input streams (deprecated)
644    pub inputTab: *mut *mut _xmlParserInput, // Stack of inputs
645    // Node analysis stack
646    pub node: *mut _xmlNode,         // Current element (deprecated)
647    pub nodeNr: c_int,               // Depth of parsing stack (deprecated)
648    pub nodeMax: c_int,              // Max depth (deprecated)
649    pub nodeTab: *mut *mut _xmlNode, // Array of nodes (deprecated)
650    // Node info
651    pub record_info: c_int,             // Whether node info should be kept
652    pub node_seq: xmlParserNodeInfoSeq, // Info about each node parsed (deprecated)
653    // Error
654    pub errNo: c_int, // Error code (deprecated)
655    // Reference and external subset
656    pub hasExternalSubset: c_int, // (deprecated)
657    pub hasPErefs: c_int,         // (deprecated)
658    pub external: c_int,          // (deprecated)
659    pub valid: c_int,             // Is document valid? (deprecated)
660    pub validate: c_int,          // Validate flag (deprecated)
661    pub vctxt: _xmlValidCtxt,     // Validity context
662    // Push parser state
663    pub instate: c_int,         // (deprecated)
664    pub token: c_int,           // (deprecated)
665    pub directory: *mut c_char, // Document directory (deprecated)
666    // Node name stack
667    pub name: *const xmlChar,         // Current parsed Node (deprecated)
668    pub nameNr: c_int,                // (deprecated)
669    pub nameMax: c_int,               // (deprecated)
670    pub nameTab: *mut *const xmlChar, // (deprecated)
671    // Misc
672    pub nbChars: c_long,            // (deprecated)
673    pub checkIndex: c_long,         // (deprecated)
674    pub keepBlanks: c_int,          // (deprecated)
675    pub disableSAX: c_int,          // (deprecated)
676    pub inSubset: c_int,            // DTD parsing state (deprecated)
677    pub intSubName: *const xmlChar, // Internal subset name (deprecated)
678    pub extSubURI: *mut xmlChar,    // External subset URI (deprecated)
679    pub extSubSystem: *mut xmlChar, // External subset public ID (deprecated)
680    // xml:space values
681    pub space: *mut c_int,    // (deprecated)
682    pub spaceNr: c_int,       // (deprecated)
683    pub spaceMax: c_int,      // (deprecated)
684    pub spaceTab: *mut c_int, // (deprecated)
685    // Entity loop prevention
686    pub depth: c_int,                 // (deprecated)
687    pub entity: *mut _xmlParserInput, // (deprecated)
688    pub charset: c_int,               // (deprecated)
689    pub nodelen: c_int,               // (deprecated)
690    pub nodemem: c_int,               // (deprecated)
691    pub pedantic: c_int,              // (deprecated)
692    pub _private: *mut c_void,        // User data (deprecated)
693    pub loadsubset: c_int,            // Load external subset (deprecated)
694    pub linenumbers: c_int,           // (deprecated)
695    pub catalogs: *mut c_void,        // (deprecated)
696    pub recovery: c_int,              // Recovery mode (deprecated)
697    pub progressive: c_int,           // (deprecated)
698    pub dict: *mut c_void,            // Dictionary (deprecated)
699    pub atts: *mut *const xmlChar,    // Attributes array (deprecated)
700    pub maxatts: c_int,               // (deprecated)
701    pub docdict: c_int,               // (deprecated)
702    // Pre-interned strings
703    pub str_xml: *const xmlChar,    // (deprecated)
704    pub str_xmlns: *const xmlChar,  // (deprecated)
705    pub str_xml_ns: *const xmlChar, // (deprecated)
706    // New SAX mode
707    pub sax2: c_int,                // (deprecated)
708    pub nsNr: c_int,                // (deprecated)
709    pub nsMax: c_int,               // (deprecated)
710    pub nsTab: *mut *const xmlChar, // (deprecated)
711    pub attallocs: *mut c_uint,     // (deprecated)
712    pub pushTab: *mut c_void,       // xmlStartTag (deprecated)
713    pub attsDefault: *mut c_void,   // (deprecated)
714    pub attsSpecial: *mut c_void,   // (deprecated)
715    pub nsWellFormed: c_int,        // (deprecated)
716    pub options: c_int,             // Extra options (deprecated)
717    pub dictNames: c_int,           // (deprecated)
718    // Streaming
719    pub freeElemsNr: c_int,       // (deprecated)
720    pub freeElems: *mut _xmlNode, // (deprecated)
721    pub freeAttrsNr: c_int,       // (deprecated)
722    pub freeAttrs: *mut _xmlAttr, // (deprecated)
723    pub lastError: _xmlError,     // Last error info (deprecated)
724    pub parseMode: c_int,         // (deprecated)
725    pub nbentities: c_ulong,      // (deprecated)
726    pub sizeentities: c_ulong,    // (deprecated)
727    // HTML non-recursive parser
728    pub nodeInfo: *mut c_void,    // (deprecated)
729    pub nodeInfoNr: c_int,        // (deprecated)
730    pub nodeInfoMax: c_int,       // (deprecated)
731    pub nodeInfoTab: *mut c_void, // (deprecated)
732    pub input_id: c_int,          // (deprecated)
733    pub sizeentcopy: c_ulong,     // (deprecated)
734    pub endCheckState: c_int,     // (deprecated)
735    pub nbErrors: c_ushort,       // (deprecated)
736    pub nbWarnings: c_ushort,     // (deprecated)
737    pub maxAmpl: c_uint,          // (deprecated)
738    // Namespace database
739    pub nsdb: *mut c_void,     // (deprecated)
740    pub attrHashMax: c_uint,   // (deprecated)
741    pub attrHash: *mut c_void, // (deprecated)
742    // Error handler
743    pub errorHandler: Option<xmlStructuredErrorFunc>, // (deprecated)
744    pub errorCtxt: *mut c_void,                       // (deprecated)
745    // Resource loader
746    pub resourceLoader: Option<xmlResourceLoader>, // (deprecated)
747    pub resourceCtxt: *mut c_void,                 // (deprecated)
748    // Encoding conversion
749    pub convImpl: Option<xmlCharEncConvImpl>, // (deprecated)
750    pub convCtxt: *mut c_void,                // (deprecated)
751}
752
753// ── xmlValidCtxt ────────────────────────────────────────────────────────
754//
755// Source: valid.h
756
757/// Validation context.
758#[repr(C)]
759pub struct _xmlValidCtxt {
760    pub userData: *mut c_void,                   // User specific data
761    pub error: Option<xmlValidityErrorFunc>,     // Error callback
762    pub warning: Option<xmlValidityWarningFunc>, // Warning callback
763    pub node: *mut _xmlNode,                     // Current parsed Node
764    pub nodeNr: c_int,                           // Depth of the parsing stack
765    pub nodeMax: c_int,                          // Max depth
766    pub nodeTab: *mut *mut _xmlNode,             // Array of nodes
767    pub flags: c_uint,                           // Internal flags
768    pub doc: *mut _xmlDoc,                       // The document
769    pub valid: c_int,                            // Temporary validity check result
770    pub vstate: *mut c_void,                     // Current validation state
771    pub vstateNr: c_int,                         // Depth of validation stack
772    pub vstateMax: c_int,                        // Max depth
773    pub vstateTab: *mut c_void,                  // Array of validation states
774    pub am: *mut c_void,                         // Automata
775    pub state: *mut c_void,                      // Automata state
776}
777
778// ── xmlID / xmlRef (valid.h ID/IDREF table entries) ────────────────────
779//
780// Source: tree.h `struct _xmlID` / `struct _xmlRef` (opaque upstream).
781
782/// An XML ID instance (ID table entry).
783#[repr(C)]
784pub struct _xmlID {
785    pub next: *mut _xmlID,    // next ID
786    pub value: *mut xmlChar,  // The ID name
787    pub attr: *mut _xmlAttr,  // The attribute holding it
788    pub name: *const xmlChar, // The attribute if attr is not available
789    pub lineno: c_int,        // The line number if attr is not available
790    pub doc: *mut _xmlDoc,    // The document holding the ID
791}
792
793/// An XML IDREF instance (ref table entry).
794#[repr(C)]
795pub struct _xmlRef {
796    pub next: *mut _xmlRef,    // next Ref
797    pub value: *const xmlChar, // The Ref name
798    pub attr: *mut _xmlAttr,   // The attribute holding it
799    pub name: *const xmlChar,  // The attribute if attr is not available
800    pub lineno: c_int,         // The line number if attr is not available
801}
802
803// ── xmlParserNodeInfo ───────────────────────────────────────────────────
804
805/// Node info for parser tracking.
806#[repr(C)]
807pub struct _xmlParserNodeInfo {
808    pub node: *const _xmlNode,
809    pub begin_pos: c_ulong,
810    pub begin_line: c_ulong,
811    pub end_pos: c_ulong,
812    pub end_line: c_ulong,
813}
814
815/// Node info sequence.
816#[repr(C)]
817pub struct _xmlParserNodeInfoSeq {
818    pub maximum: c_ulong,
819    pub length: c_ulong,
820    pub buffer: *mut _xmlParserNodeInfo,
821}
822
823/// Typedef alias for `_xmlParserNodeInfoSeq`.
824pub type xmlParserNodeInfoSeq = _xmlParserNodeInfoSeq;
825
826// ── xmlXPathContext ─────────────────────────────────────────────────────
827//
828// Source: xpath.h
829
830/// XPath evaluation context.
831#[repr(C)]
832pub struct _xmlXPathContext {
833    pub doc: *mut _xmlDoc,                                 // The current document
834    pub node: *mut _xmlNode,                               // The current node
835    pub nb_variables_unused: c_int,                        // (unused)
836    pub max_variables_unused: c_int,                       // (unused)
837    pub varHash: *mut c_void,                              // Hash table of defined variables
838    pub nb_types: c_int,                                   // Number of defined types
839    pub max_types: c_int,                                  // Max number of types
840    pub types: *mut c_void,                                // Array of defined types (xmlXPathType)
841    pub nb_funcs_unused: c_int,                            // (unused)
842    pub max_funcs_unused: c_int,                           // (unused)
843    pub funcHash: *mut c_void,                             // Hash table of defined funcs
844    pub nb_axis: c_int,                                    // Number of defined axis
845    pub max_axis: c_int,                                   // Max number of axis
846    pub axis: *mut c_void,                                 // Array of defined axis (xmlXPathAxis)
847    pub namespaces: *mut *mut _xmlNs,                      // Array of namespaces
848    pub nsNr: c_int,                                       // Number of namespaces in scope
849    pub user: *mut c_void,                                 // Function to free
850    pub contextSize: c_int,                                // Context size
851    pub proximityPosition: c_int,                          // Proximity position
852    pub xptr: c_int,                                       // XPointer context?
853    pub here: *mut _xmlNode,                               // For here()
854    pub origin: *mut _xmlNode,                             // For origin()
855    pub nsHash: *mut c_void,                               // Namespaces hash table
856    pub varLookupFunc: Option<xmlXPathVariableLookupFunc>, // Variable lookup func
857    pub varLookupData: *mut c_void,                        // Variable lookup data
858    pub extra: *mut c_void,                                // Needed for XSLT
859    pub function: *const xmlChar,                          // Function name when calling a function
860    pub functionURI: *const xmlChar,                       // Function namespace URI
861    pub funcLookupFunc: Option<xmlXPathFuncLookupFunc>,    // Function lookup func
862    pub funcLookupData: *mut c_void,                       // Function lookup data
863    pub tmpNsList: *mut *mut _xmlNs,                       // Array of temp namespaces
864    pub tmpNsNr: c_int,                                    // Number of temp namespaces
865    pub userData: *mut c_void,                             // User specific data
866    pub error: Option<xmlStructuredErrorFunc>,             // Error callback
867    pub lastError: _xmlError,                              // Last error
868    pub debugNode: *mut _xmlNode,                          // Source node (XSLT)
869    pub dict: *mut c_void,                                 // Dictionary
870    pub flags: c_int,                                      // Compilation flags
871    pub cache: *mut c_void,                                // Cache for XPath objects
872    pub opLimit: c_ulong,                                  // Resource limits
873    pub opCount: c_ulong,
874    pub depth: c_int,
875}
876
877// ── xmlXPathObject ──────────────────────────────────────────────────────
878//
879// Source: xpath.h
880
881/// XPath evaluated object.
882#[repr(C)]
883pub struct _xmlXPathObject {
884    pub type_: c_int,            // Object type
885    pub nodesetval: *mut c_void, // Node set (xmlNodeSet)
886    pub boolval: c_int,          // Boolean value
887    pub floatval: f64,           // Number value
888    pub stringval: *mut xmlChar, // String value
889    pub user: *mut c_void,       // User pointer
890    pub index: c_int,            // Index
891    pub user2: *mut c_void,      // User pointer 2
892    pub index2: c_int,           // Index 2
893}
894
895// ── Node set (contained within XPath objects) ───────────────────────────
896
897/// XPath node set.
898#[repr(C)]
899pub struct _xmlNodeSet {
900    pub nodeNr: c_int,               // Number of nodes
901    pub nodeMax: c_int,              // Max number of nodes
902    pub nodeTab: *mut *mut _xmlNode, // Array of nodes
903}
904
905// ── XSLT types ──────────────────────────────────────────────────────────
906//
907// ═══════════════════════════════════════════════════════════════════════════════
908// XSLT Types (Phase 8)
909// ═══════════════════════════════════════════════════════════════════════════════
910// Source: xslt.h, xsltInternals.h (from libxslt)
911
912/// XSLT stylesheet — the compiled representation of an XSLT stylesheet.
913///
914/// # UPSTREAM-PARITY
915///
916/// Layout matches upstream `_xsltStylesheet` from xsltInternals.h (libxslt
917/// 1.1.45); field order and types match the C struct exactly for ABI
918/// compatibility. Verified by the RUST-MIRROR-ABI court
919/// (tools/abi/rust_mirror_court.py). Courts: XSLT-STYLESHEET-*
920#[repr(C)]
921pub struct _xsltStylesheet {
922    pub parent: *mut _xsltStylesheet,   // parent stylesheet (imports)
923    pub next: *mut _xsltStylesheet,     // next stylesheet in imports
924    pub imports: *mut _xsltStylesheet,  // list of imported stylesheets
925    pub docList: *mut _xsltDocument,    // documents of this stylesheet
926    pub doc: *mut _xmlDoc,              // the stylesheet document
927    pub stripSpaces: *mut c_void,       // xmlHashTablePtr: elements to strip
928    pub stripAll: c_int,                // strip all whitespace
929    pub cdataSection: *mut c_void,      // xmlHashTablePtr
930    pub variables: *mut _xsltStackElem, // global variables/params (list)
931    pub templates: *mut _xsltTemplate,  // ordered templates (highest first)
932    pub templatesHash: *mut c_void,     // xmlHashTablePtr: template lookup
933    pub rootMatch: *mut c_void,         // xsltCompMatchPtr
934    pub keyMatch: *mut c_void,
935    pub elemMatch: *mut c_void,
936    pub attrMatch: *mut c_void,
937    pub parentMatch: *mut c_void,
938    pub textMatch: *mut c_void,
939    pub piMatch: *mut c_void,
940    pub commentMatch: *mut c_void,
941    pub nsAliases: *mut c_void,     // xmlHashTablePtr
942    pub attributeSets: *mut c_void, // xmlHashTablePtr
943    pub nsHash: *mut c_void,        // xmlHashTablePtr
944    pub nsDefs: *mut c_void,
945    pub keys: *mut c_void,    // void *: key definitions
946    pub method: *mut xmlChar, // output method
947    pub methodURI: *mut xmlChar,
948    pub version: *mut xmlChar,
949    pub encoding: *mut xmlChar,
950    pub omitXmlDeclaration: c_int,
951    pub decimalFormat: *mut _xsltDecimalFormat, // xsltDecimalFormatPtr
952    pub standalone: c_int,
953    pub doctypePublic: *mut xmlChar,
954    pub doctypeSystem: *mut xmlChar,
955    pub indent: c_int,
956    pub mediaType: *mut xmlChar,
957    pub preComps: *mut c_void, // xsltElemPreCompPtr
958    pub warnings: c_int,
959    pub errors: c_int,
960    pub exclPrefix: *mut xmlChar,
961    pub exclPrefixTab: *mut *mut xmlChar,
962    pub exclPrefixNr: c_int,
963    pub exclPrefixMax: c_int,
964    pub _private: *mut c_void,
965    pub extInfos: *mut c_void, // xmlHashTablePtr
966    pub extrasNr: c_int,
967    pub includes: *mut _xsltDocument, // xsltDocumentPtr
968    pub dict: *mut c_void,            // xmlDictPtr
969    pub attVTs: *mut c_void,
970    pub defaultAlias: *const xmlChar,
971    pub nopreproc: c_int,
972    pub internalized: c_int,
973    pub literal_result: c_int,
974    pub principal: *mut _xsltStylesheet, // xsltStylesheetPtr
975    // UPSTREAM-PARITY: `compCtxt` and `principalData` sit inside
976    // `#ifdef XSLT_REFACTORED` in xsltInternals.h and are absent from the
977    // oracle layout (system libxslt 1.1.45 ships with XSLT_REFACTORED
978    // disabled; verified against the installed xsltInternals.h). The mirror
979    // intentionally omits them so field offsets match the oracle DSO.
980    pub forwards_compatible: c_int,
981    pub namedTemplates: *mut c_void,      // xmlHashTablePtr
982    pub xpathCtxt: *mut _xmlXPathContext, // xmlXPathContextPtr
983    pub opLimit: c_ulong,
984    pub opCount: c_ulong,
985}
986
987/// XSLT transform context — runtime state during a transformation.
988///
989/// # ABI
990///
991/// Layout mirrors upstream `struct _xsltTransformContext` (libxslt 1.1.42
992/// xsltInternals.h). The runtime keeps the XPath value stack on
993/// `xpathCtxt->value*` (upstream behaviour); there is no separate return
994/// stack in the context.
995#[repr(C)]
996pub struct _xsltTransformContext {
997    pub style: *mut _xsltStylesheet, // stylesheet being applied
998    pub type_: c_int,                // xsltOutputType
999    pub templ: *mut _xsltTemplate,   // current template
1000    pub templNr: c_int,
1001    pub templMax: c_int,
1002    pub templTab: *mut *mut _xsltTemplate, // xsltTemplatePtr *
1003    pub vars: *mut _xsltStackElem,         // current variable stack head
1004    pub varsNr: c_int,
1005    pub varsMax: c_int,
1006    pub varsTab: *mut *mut _xsltStackElem, // xsltStackElemPtr *
1007    pub varsBase: c_int,
1008    pub extFunctions: *mut c_void, // xmlHashTablePtr
1009    pub extElements: *mut c_void,  // xmlHashTablePtr
1010    pub extInfos: *mut c_void,     // xmlHashTablePtr
1011    pub mode: *const xmlChar,
1012    pub modeURI: *const xmlChar,
1013    pub docList: *mut _xsltDocument,      // xsltDocumentPtr
1014    pub document: *mut _xsltDocument,     // xsltDocumentPtr (current doc)
1015    pub node: *mut _xmlNode,              // current source node
1016    pub nodeList: *mut _xmlNodeSet,       // xmlNodeSetPtr
1017    pub output: *mut _xmlDoc,             // current result document
1018    pub insert: *mut _xmlNode,            // insertion point
1019    pub xpathCtxt: *mut _xmlXPathContext, // xmlXPathContextPtr
1020    pub state: c_int,                     // xsltTransformState
1021    pub globalVars: *mut c_void,          // xmlHashTablePtr
1022    pub inst: *mut _xmlNode,              // current instruction node
1023    pub xinclude: c_int,
1024    pub outputFile: *const c_char, // const char *
1025    pub profile: c_int,
1026    pub prof: c_long,
1027    pub profNr: c_int,
1028    pub profMax: c_int,
1029    pub profTab: *mut c_long, // long *
1030    pub _private: *mut c_void,
1031    pub extrasNr: c_int,
1032    pub extrasMax: c_int,
1033    pub extras: *mut c_void,                // xsltRuntimeExtraPtr
1034    pub styleList: *mut _xsltDocument,      // xsltDocumentPtr
1035    pub sec: *mut c_void,                   // xsltSecurityPrefsPtr
1036    pub error: Option<xmlGenericErrorFunc>, // xmlGenericErrorFunc
1037    pub errctx: *mut c_void,
1038    pub sortfunc: *mut c_void,    // xsltSortFunc
1039    pub tmpRVT: *mut _xmlDoc,     // xmlDocPtr
1040    pub persistRVT: *mut _xmlDoc, // xmlDocPtr
1041    pub ctxtflags: c_int,
1042    pub lasttext: *const xmlChar,
1043    pub lasttsize: c_int,
1044    pub lasttuse: c_int,
1045    pub debugStatus: c_int,
1046    pub traceCode: *mut c_ulong, // unsigned long *
1047    pub parserOptions: c_int,
1048    pub dict: *mut c_void,    // xmlDictPtr
1049    pub tmpDoc: *mut _xmlDoc, // xmlDocPtr
1050    pub internalized: c_int,
1051    pub nbKeys: c_int,
1052    pub hasTemplKeyPatterns: c_int,
1053    pub currentTemplateRule: *mut _xsltTemplate, // xsltTemplatePtr
1054    pub initialContextNode: *mut _xmlNode,       // xmlNodePtr
1055    pub initialContextDoc: *mut _xmlDoc,         // xmlDocPtr
1056    pub cache: *mut c_void,                      // xsltTransformCachePtr
1057    pub contextVariable: *mut c_void,
1058    pub localRVT: *mut _xmlDoc,     // xmlDocPtr
1059    pub localRVTBase: *mut _xmlDoc, // xmlDocPtr
1060    pub keyInitLevel: c_int,
1061    pub depth: c_int,
1062    pub maxTemplateDepth: c_int,
1063    pub maxTemplateVars: c_int,
1064    pub opLimit: c_ulong,
1065    pub opCount: c_ulong,
1066    pub sourceDocDirty: c_int,
1067    pub currentId: c_ulong,
1068    pub newLocale: *mut c_void,  // xsltNewLocaleFunc
1069    pub freeLocale: *mut c_void, // xsltFreeLocaleFunc
1070    pub genSortKey: *mut c_void, // xsltGenSortKeyFunc
1071}
1072
1073/// XSLT compiled template.
1074///
1075/// # ABI
1076///
1077/// Layout mirrors upstream `struct _xsltTemplate` (xsltInternals.h).
1078#[repr(C)]
1079pub struct _xsltTemplate {
1080    pub next: *mut _xsltTemplate,    // next template in list
1081    pub style: *mut _xsltStylesheet, // owning stylesheet
1082    pub r#match: *mut xmlChar,       // match pattern (compiled string)
1083    pub priority: f32,               // float
1084    pub name: *const xmlChar,        // template name (named templates)
1085    pub nameURI: *const xmlChar,
1086    pub mode: *const xmlChar, // template mode
1087    pub modeURI: *const xmlChar,
1088    pub content: *mut _xmlNode, // template content
1089    pub elem: *mut _xmlNode,    // the xsl:template node
1090    pub inheritedNsNr: c_int,
1091    pub inheritedNs: *mut *mut _xmlNs, // xmlNsPtr *
1092    pub nbCalls: c_int,
1093    pub time: c_ulong,
1094    pub params: *mut c_void,
1095    pub templNr: c_int,
1096    pub templMax: c_int,
1097    pub templCalledTab: *mut *mut _xsltTemplate, // xsltTemplatePtr *
1098    pub templCountTab: *mut c_int,               // int *
1099    pub position: c_int,
1100}
1101
1102/// XSLT document wrapper.
1103///
1104/// # ABI
1105///
1106/// Layout mirrors upstream `struct _xsltDocument` (xsltInternals.h).
1107#[repr(C)]
1108pub struct _xsltDocument {
1109    pub next: *mut _xsltDocument,     // next document in list
1110    pub main: c_int,                  // is this the main stylesheet doc?
1111    pub doc: *mut _xmlDoc,            // the wrapped document
1112    pub keys: *mut c_void,            // void *
1113    pub includes: *mut _xsltDocument, // list of included documents
1114    pub preproc: c_int,               // pre-proc flag
1115    pub nbKeysComputed: c_int,
1116}
1117
1118/// XSLT key definition.
1119///
1120/// # ABI
1121///
1122/// Layout mirrors upstream `struct _xsltKeyDef` (xsltInternals.h).
1123#[repr(C)]
1124pub struct _xsltKeyDef {
1125    pub next: *mut _xsltKeyDef,   // next key definition
1126    pub inst: *mut _xmlNode,      // the xsl:key instruction node
1127    pub name: *mut xmlChar,       // key name
1128    pub nameURI: *mut xmlChar,    // key namespace URI
1129    pub r#match: *mut xmlChar,    // match pattern
1130    pub r#use: *mut xmlChar,      // use expression
1131    pub comp: *mut c_void,        // xmlXPathCompExprPtr
1132    pub usecomp: *mut c_void,     // xmlXPathCompExprPtr
1133    pub nsList: *mut *mut _xmlNs, // xmlNsPtr *
1134    pub nsNr: c_int,
1135}
1136
1137/// XSLT key table entry.
1138///
1139/// # ABI
1140///
1141/// Layout mirrors upstream `struct _xsltKeyTable` (xsltInternals.h).
1142#[repr(C)]
1143pub struct _xsltKeyTable {
1144    pub next: *mut _xsltKeyTable, // next key table
1145    pub name: *mut xmlChar,       // key name
1146    pub nameURI: *mut xmlChar,    // key namespace URI
1147    pub keys: *mut c_void,        // xmlHashTablePtr
1148}
1149
1150/// XSLT stack element (variable/parameter binding).
1151///
1152/// # ABI
1153///
1154/// Layout mirrors upstream `struct _xsltStackElem` (xsltInternals.h).
1155#[repr(C)]
1156pub struct _xsltStackElem {
1157    pub next: *mut _xsltStackElem,           // next stack element
1158    pub comp: *mut c_void,                   // xsltStylePreCompPtr
1159    pub computed: c_int,                     // was the value computed?
1160    pub name: *const xmlChar,                // variable/parameter name
1161    pub nameURI: *const xmlChar,             // namespace URI
1162    pub select: *const xmlChar,              // select expression
1163    pub tree: *mut _xmlNode,                 // content tree (inline content)
1164    pub value: *mut _xmlXPathObject,         // evaluated value (xmlXPathObjectPtr)
1165    pub fragment: *mut _xmlDoc,              // xmlDocPtr (RVT)
1166    pub level: c_int,                        // scope level
1167    pub context: *mut _xsltTransformContext, // xsltTransformContextPtr
1168    pub flags: c_int,
1169}
1170
1171/// XSLT decimal format definition.
1172///
1173/// # ABI
1174///
1175/// Layout mirrors upstream `struct _xsltDecimalFormat` (xsltInternals.h).
1176#[repr(C)]
1177pub struct _xsltDecimalFormat {
1178    pub next: *mut _xsltDecimalFormat, // next decimal format
1179    pub name: *mut xmlChar,            // format name (NULL = default)
1180    pub digit: *mut xmlChar,
1181    pub patternSeparator: *mut xmlChar,
1182    pub minusSign: *mut xmlChar,
1183    pub infinity: *mut xmlChar,
1184    pub noNumber: *mut xmlChar,
1185    pub decimalPoint: *mut xmlChar,
1186    pub grouping: *mut xmlChar,
1187    pub percent: *mut xmlChar,
1188    pub permille: *mut xmlChar,
1189    pub zeroDigit: *mut xmlChar,
1190    pub nsUri: *const xmlChar,
1191}
1192
1193/// XSLT namespace alias.
1194///
1195/// # UPSTREAM-PARITY
1196///
1197/// Layout matches upstream `_xsltNsAlias` from xsltInternals.h.
1198#[repr(C)]
1199pub struct _xsltNsAlias {
1200    /// Next namespace alias.
1201    pub next: *mut _xsltNsAlias,
1202
1203    /// Result namespace URI.
1204    pub resultNs: *const xmlChar,
1205
1206    /// Stylesheet namespace URI.
1207    pub styleNs: *const xmlChar,
1208}
1209
1210/// XSLT attribute set.
1211///
1212/// # UPSTREAM-PARITY
1213///
1214/// Layout matches upstream `_xsltAttrSet` from xsltInternals.h.
1215#[repr(C)]
1216pub struct _xsltAttrSet {
1217    /// Next attribute set.
1218    pub next: *mut _xsltAttrSet,
1219
1220    /// Attribute set name.
1221    pub name: *const xmlChar,
1222
1223    /// Attribute set namespace URI.
1224    pub ns: *const xmlChar,
1225
1226    /// The xsl:attribute-set instruction node.
1227    pub inst: *mut _xmlNode,
1228
1229    /// Owning stylesheet.
1230    pub style: *mut _xsltStylesheet,
1231
1232    /// Import depth.
1233    pub depth: c_int,
1234}
1235
1236/// XSLT sort element.
1237///
1238/// # UPSTREAM-PARITY
1239///
1240/// Layout matches upstream `_xsltSort` from xsltInternals.h.
1241#[repr(C)]
1242pub struct _xsltSort {
1243    /// Next sort element.
1244    pub next: *mut _xsltSort,
1245
1246    /// The xsl:sort instruction node.
1247    pub inst: *mut _xmlNode,
1248
1249    /// The sort key select expression.
1250    pub select: *const xmlChar,
1251
1252    /// Language for sorting.
1253    pub lang: *const xmlChar,
1254
1255    /// Data type ("text" or "number").
1256    pub dataType: *const xmlChar,
1257
1258    /// Sort order ("ascending" or "descending").
1259    pub order: *const xmlChar,
1260
1261    /// Case order ("upper-first" or "lower-first").
1262    pub caseOrder: *const xmlChar,
1263
1264    /// Whether this sort is a text sort.
1265    pub isText: c_int,
1266
1267    /// Whether the select expression was a constant.
1268    pub hasConst: c_int,
1269
1270    /// Locale information.
1271    pub locale: *mut c_void,
1272
1273    /// Owning stylesheet.
1274    pub style: *mut _xsltStylesheet,
1275
1276    /// Import depth.
1277    pub depth: c_int,
1278}
1279
1280// ── Type aliases for pointer types ──────────────────────────────────────
1281
1282pub type xmlNodePtr = *mut _xmlNode;
1283pub type xmlDocPtr = *mut _xmlDoc;
1284pub type xmlNsPtr = *mut _xmlNs;
1285pub type xmlAttrPtr = *mut _xmlAttr;
1286pub type xmlDtdPtr = *mut _xmlDtd;
1287pub type xmlEntityPtr = *mut _xmlEntity;
1288pub type xmlErrorPtr = *mut _xmlError;
1289pub type xmlParserCtxtPtr = *mut _xmlParserCtxt;
1290pub type xmlParserInputPtr = *mut _xmlParserInput;
1291pub type xmlParserInputBufferPtr = *mut _xmlParserInputBuffer;
1292pub type xmlOutputBufferPtr = *mut _xmlOutputBuffer;
1293pub type xmlSAXHandlerPtr = *mut _xmlSAXHandler;
1294pub type xmlValidCtxtPtr = *mut _xmlValidCtxt;
1295pub type xmlBufferPtr = *mut _xmlBuffer;
1296pub type xmlElementPtr = *mut _xmlElement;
1297pub type xmlElementContentPtr = *mut _xmlElementContent;
1298pub type xmlNotationPtr = *mut _xmlNotation;
1299pub type xmlEnumerationPtr = *mut _xmlEnumeration;
1300pub type xmlAttributeDeclPtr = *mut _xmlAttribute;
1301pub type xmlXPathContextPtr = *mut _xmlXPathContext;
1302pub type xmlXPathObjectPtr = *mut _xmlXPathObject;
1303pub type xmlNodeSetPtr = *mut _xmlNodeSet;
1304pub type xmlCharEncodingHandlerPtr = *mut _xmlCharEncodingHandler;
1305pub type xmlBufPtr = *mut _xmlBuf;
1306pub type xsltStylesheetPtr = *mut _xsltStylesheet;
1307pub type xsltTransformContextPtr = *mut _xsltTransformContext;
1308pub type xsltTemplatePtr = *mut _xsltTemplate;
1309pub type xsltKeyDefPtr = *mut _xsltKeyDef;
1310pub type xsltKeyTablePtr = *mut _xsltKeyTable;
1311pub type xsltStackElemPtr = *mut _xsltStackElem;
1312pub type xsltDecimalFormatPtr = *mut _xsltDecimalFormat;
1313pub type xsltNsAliasPtr = *mut _xsltNsAlias;
1314pub type xsltAttrSetPtr = *mut _xsltAttrSet;
1315pub type xsltDocumentPtr = *mut _xsltDocument;
1316pub type xsltSortPtr = *mut _xsltSort;
1317
1318#[cfg(test)]
1319mod parser_ctxt_abi_layout {
1320    //! ABI-layout guard for `_xmlParserCtxt` / `_xmlEntity` / `_xmlSAXHandler`
1321    //! (SP-14.3.1-4, bug71592). `ctxt->instate`, `wellFormed`, `myDoc`,
1322    //! `inSubset` etc. are read by foreign consumers compiled against the real
1323    //! libxml2 headers (PHP ext/xml expat-compat `compat.c` reads them while
1324    //! resolving entity references), so the Rust struct offsets must equal the
1325    //! upstream header's `offsetof` values — measured against the 2.15.3 oracle
1326    //! with courts/suites/phase14/consumers/ctxoffset-probe.c (its output is
1327    //! reproduced in the assertions below).
1328    use super::*;
1329    use core::mem::offset_of;
1330
1331    #[test]
1332    fn parser_ctxt_layout_matches_upstream_headers() {
1333        assert_eq!(core::mem::size_of::<_xmlParserCtxt>(), 840);
1334        assert_eq!(offset_of!(_xmlParserCtxt, sax), 0);
1335        assert_eq!(offset_of!(_xmlParserCtxt, userData), 8);
1336        assert_eq!(offset_of!(_xmlParserCtxt, myDoc), 16);
1337        assert_eq!(offset_of!(_xmlParserCtxt, wellFormed), 24);
1338        assert_eq!(offset_of!(_xmlParserCtxt, input), 56);
1339        assert_eq!(offset_of!(_xmlParserCtxt, errNo), 136);
1340        assert_eq!(offset_of!(_xmlParserCtxt, vctxt), 160);
1341        assert_eq!(core::mem::size_of::<_xmlValidCtxt>(), 112);
1342        assert_eq!(offset_of!(_xmlParserCtxt, instate), 272);
1343        assert_eq!(offset_of!(_xmlParserCtxt, disableSAX), 332);
1344        assert_eq!(offset_of!(_xmlParserCtxt, inSubset), 336);
1345    }
1346
1347    #[test]
1348    fn entity_and_sax_handler_layout_matches_upstream_headers() {
1349        assert_eq!(core::mem::size_of::<_xmlEntity>(), 144);
1350        assert_eq!(offset_of!(_xmlEntity, name), 16);
1351        assert_eq!(offset_of!(_xmlEntity, content), 80);
1352        assert_eq!(offset_of!(_xmlEntity, etype), 92);
1353        assert_eq!(offset_of!(_xmlEntity, ExternalID), 96);
1354        assert_eq!(offset_of!(_xmlEntity, SystemID), 104);
1355        assert_eq!(core::mem::size_of::<_xmlSAXHandler>(), 256);
1356        assert_eq!(offset_of!(_xmlSAXHandler, getEntity), 40);
1357        assert_eq!(offset_of!(_xmlSAXHandler, startElement), 112);
1358        assert_eq!(offset_of!(_xmlSAXHandler, initialized), 216);
1359        assert_eq!(offset_of!(_xmlSAXHandler, startElementNs), 232);
1360    }
1361}