Skip to main content

libxml_rs/abi/
callbacks.rs

1//! C ABI callback function type definitions — matching upstream callback signatures (§14, §20).
2//!
3//! This module defines all function pointer types used in public upstream structures:
4//! SAX1 callbacks, SAX2 callbacks, error callbacks, validity callbacks, XPath callbacks,
5//! I/O callbacks, resource loader callbacks, encoding callbacks, and the SAX locator.
6//!
7//! # Phase 1 status
8//!
9//! Complete — all callback types from upstream headers are defined.
10//!
11//! # Safety
12//!
13//! All callback types are `unsafe extern "C"` because they are called across the FFI boundary
14//! with C calling conventions. The caller must ensure:
15//! - Function pointers are non-null before invocation (unless nullable per upstream contract)
16//! - Pointers passed to callbacks remain valid for the callback's duration
17//! - Callbacks observe the upstream ownership/lifetime contract
18//! - Thread safety matches upstream expectations
19
20#![allow(non_camel_case_types)]
21
22use core::ffi::c_void;
23use std::os::raw::{c_char, c_int, c_uchar};
24
25use crate::abi::structs::*;
26
27// ═══════════════════════════════════════════════════════════════════════════════
28// SAX1 Callbacks (xmlSAXHandler)
29// ═══════════════════════════════════════════════════════════════════════════════
30
31/// Callback for internal DTD subset notification.
32///
33/// # UPSTREAM-PARITY
34///
35/// Oracle behavior: Called when `<!DOCTYPE ... [ ... ]>` internal subset is parsed.
36/// Parameters are the DOCTYPE name, external ID (or NULL), system ID (or NULL).
37pub type internalSubsetSAXFunc = unsafe extern "C" fn(
38    ctx: *mut c_void,
39    name: *const crate::abi::types::xmlChar,
40    ExternalID: *const crate::abi::types::xmlChar,
41    SystemID: *const crate::abi::types::xmlChar,
42);
43
44/// Callback for standalone document declaration.
45///
46/// Returns 1 if standalone="yes", 0 if standalone="no", -1 if not declared.
47pub type isStandaloneSAXFunc = unsafe extern "C" fn(ctx: *mut c_void) -> c_int;
48
49/// Callback: does the document have an internal subset?
50pub type hasInternalSubsetSAXFunc = unsafe extern "C" fn(ctx: *mut c_void) -> c_int;
51
52/// Callback: does the document have an external subset?
53pub type hasExternalSubsetSAXFunc = unsafe extern "C" fn(ctx: *mut c_void) -> c_int;
54
55/// Callback to resolve an external entity.
56///
57/// Returns a newly allocated `xmlParserInputPtr` or NULL.
58///
59/// # UPSTREAM-PARITY
60///
61/// Ownership: The returned `xmlParserInputPtr` is owned by the parser context.
62pub type resolveEntitySAXFunc = unsafe extern "C" fn(
63    ctx: *mut c_void,
64    publicId: *const crate::abi::types::xmlChar,
65    systemId: *const crate::abi::types::xmlChar,
66) -> *mut _xmlParserInput;
67
68/// Callback to get an entity.
69///
70/// Returns a pointer to an entity or NULL.
71///
72/// # UPSTREAM-PARITY
73///
74/// Ownership: The returned entity is owned by the document's entity table.
75/// The caller must not free it.
76pub type getEntitySAXFunc = unsafe extern "C" fn(
77    ctx: *mut c_void,
78    name: *const crate::abi::types::xmlChar,
79) -> *mut _xmlEntity;
80
81/// Callback for entity declaration.
82pub type entityDeclSAXFunc = unsafe extern "C" fn(
83    ctx: *mut c_void,
84    name: *const crate::abi::types::xmlChar,
85    type_: c_int,
86    publicId: *const crate::abi::types::xmlChar,
87    systemId: *const crate::abi::types::xmlChar,
88    content: *mut crate::abi::types::xmlChar,
89);
90
91/// Callback for notation declaration.
92pub type notationDeclSAXFunc = unsafe extern "C" fn(
93    ctx: *mut c_void,
94    name: *const crate::abi::types::xmlChar,
95    publicId: *const crate::abi::types::xmlChar,
96    systemId: *const crate::abi::types::xmlChar,
97);
98
99/// Callback for attribute declaration.
100pub type attributeDeclSAXFunc = unsafe extern "C" fn(
101    ctx: *mut c_void,
102    elem: *const crate::abi::types::xmlChar,
103    name: *const crate::abi::types::xmlChar,
104    type_: c_int,
105    def: c_int,
106    defaultValue: *const crate::abi::types::xmlChar,
107    tree: *mut _xmlEnumeration,
108);
109
110/// Callback for element declaration.
111pub type elementDeclSAXFunc = unsafe extern "C" fn(
112    ctx: *mut c_void,
113    name: *const crate::abi::types::xmlChar,
114    type_: c_int,
115    content: *mut _xmlElementContent,
116);
117
118/// Callback for unparsed entity declaration.
119pub type unparsedEntityDeclSAXFunc = unsafe extern "C" fn(
120    ctx: *mut c_void,
121    name: *const crate::abi::types::xmlChar,
122    publicId: *const crate::abi::types::xmlChar,
123    systemId: *const crate::abi::types::xmlChar,
124    notationName: *const crate::abi::types::xmlChar,
125);
126
127/// Callback to set the document locator.
128///
129/// # UPSTREAM-PARITY
130///
131/// The locator is an opaque structure that provides line/column information.
132pub type setDocumentLocatorSAXFunc =
133    unsafe extern "C" fn(ctx: *mut c_void, loc: *mut _xmlSAXLocator);
134
135/// Callback for document start.
136pub type startDocumentSAXFunc = unsafe extern "C" fn(ctx: *mut c_void);
137
138/// Callback for document end.
139pub type endDocumentSAXFunc = unsafe extern "C" fn(ctx: *mut c_void);
140
141/// Callback for element start (SAX1).
142///
143/// # Parameters
144/// - `name`: element name
145/// - `atts`: NULL-terminated array of [name, value, name, value, ..., NULL]
146pub type startElementSAXFunc = unsafe extern "C" fn(
147    ctx: *mut c_void,
148    name: *const crate::abi::types::xmlChar,
149    atts: *mut *const crate::abi::types::xmlChar,
150);
151
152/// Callback for element end (SAX1).
153pub type endElementSAXFunc =
154    unsafe extern "C" fn(ctx: *mut c_void, name: *const crate::abi::types::xmlChar);
155
156/// Callback for entity reference.
157pub type referenceSAXFunc =
158    unsafe extern "C" fn(ctx: *mut c_void, name: *const crate::abi::types::xmlChar);
159
160/// Callback for character data.
161pub type charactersSAXFunc =
162    unsafe extern "C" fn(ctx: *mut c_void, ch: *const crate::abi::types::xmlChar, len: c_int);
163
164/// Callback for ignorable whitespace.
165pub type ignorableWhitespaceSAXFunc =
166    unsafe extern "C" fn(ctx: *mut c_void, ch: *const crate::abi::types::xmlChar, len: c_int);
167
168/// Callback for processing instructions.
169pub type processingInstructionSAXFunc = unsafe extern "C" fn(
170    ctx: *mut c_void,
171    target: *const crate::abi::types::xmlChar,
172    data: *const crate::abi::types::xmlChar,
173);
174
175/// Callback for comments.
176pub type commentSAXFunc =
177    unsafe extern "C" fn(ctx: *mut c_void, value: *const crate::abi::types::xmlChar);
178
179/// Callback for warnings (printf-style, variadic at C call site).
180///
181/// # UPSTREAM-PARITY
182///
183/// The `...` is implicit in C; Rust type cannot express variadic extern "C"
184/// on stable. The function pointer ABI is identical — C callers pass variadic
185/// arguments and the callee uses va_list internally.
186pub type warningSAXFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
187
188/// Callback for errors (printf-style, variadic at C call site).
189pub type errorSAXFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
190
191/// Callback for fatal errors (printf-style, variadic at C call site).
192pub type fatalErrorSAXFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
193
194/// Callback to get a parameter entity.
195///
196/// Returns a pointer to a parameter entity or NULL.
197pub type getParameterEntitySAXFunc = unsafe extern "C" fn(
198    ctx: *mut c_void,
199    name: *const crate::abi::types::xmlChar,
200) -> *mut _xmlEntity;
201
202/// Callback for CDATA block.
203pub type cdataBlockSAXFunc =
204    unsafe extern "C" fn(ctx: *mut c_void, value: *const crate::abi::types::xmlChar, len: c_int);
205
206/// Callback for external subset notification.
207pub type externalSubsetSAXFunc = unsafe extern "C" fn(
208    ctx: *mut c_void,
209    name: *const crate::abi::types::xmlChar,
210    ExternalID: *const crate::abi::types::xmlChar,
211    SystemID: *const crate::abi::types::xmlChar,
212);
213
214/// Callback for initializing the SAX handler.
215///
216/// # UPSTREAM-PARITY
217///
218/// This is a libxml2-internal callback used to set SAX2 callbacks when SAX1 callbacks
219/// are not provided. Not typically set by downstream users.
220pub type initSAXFunc = unsafe extern "C" fn(ctx: *mut c_void, handler: *mut _xmlSAXHandler);
221
222// ═══════════════════════════════════════════════════════════════════════════════
223// SAX2 Callbacks
224// ═══════════════════════════════════════════════════════════════════════════════
225
226/// Callback for element start (SAX2/namespaced).
227///
228/// # Parameters
229/// - `localname`: element local name
230/// - `prefix`: element namespace prefix (or NULL)
231/// - `URI`: element namespace URI (or NULL)
232/// - `nb_namespaces`: number of namespace declarations
233/// - `namespaces`: array of [prefix, URI, prefix, URI, ...] (size 2*nb_namespaces)
234/// - `nb_attributes`: total number of attributes
235/// - `nb_defaulted`: number of defaulted attributes (from DTD)
236/// - `attributes`: array of [localname, prefix, URI, value, value_end, ...]
237///   each attribute is 5 entries, value_end is pointer past last char of value
238pub type startElementNsSAX2Func = unsafe extern "C" fn(
239    ctx: *mut c_void,
240    localname: *const crate::abi::types::xmlChar,
241    prefix: *const crate::abi::types::xmlChar,
242    URI: *const crate::abi::types::xmlChar,
243    nb_namespaces: c_int,
244    namespaces: *mut *const crate::abi::types::xmlChar,
245    nb_attributes: c_int,
246    nb_defaulted: c_int,
247    attributes: *mut *const crate::abi::types::xmlChar,
248);
249
250/// Callback for element end (SAX2/namespaced).
251pub type endElementNsSAX2Func = unsafe extern "C" fn(
252    ctx: *mut c_void,
253    localname: *const crate::abi::types::xmlChar,
254    prefix: *const crate::abi::types::xmlChar,
255    URI: *const crate::abi::types::xmlChar,
256);
257
258// ═══════════════════════════════════════════════════════════════════════════════
259// SAX Locator
260// ═══════════════════════════════════════════════════════════════════════════════
261
262/// The SAX locator structure providing line/column information.
263///
264/// # UPSTREAM-PARITY
265///
266/// This is an opaque structure from the perspective of SAX handlers.
267/// Upstream defines it as:
268/// ```c
269/// typedef struct _xmlSAXLocator xmlSAXLocator;
270/// typedef xmlSAXLocator *xmlSAXLocatorPtr;
271/// struct _xmlSAXLocator {
272///     xmlChar *(*getPublicId)(void *ctx);
273///     xmlChar *(*getSystemId)(void *ctx);
274///     int      (*getLineNumber)(void *ctx);
275///     int      (*getColumnNumber)(void *ctx);
276/// };
277/// ```
278#[derive(Debug)]
279#[repr(C)]
280pub struct _xmlSAXLocator {
281    /// Get the public ID of the current document position.
282    pub getPublicId:
283        Option<unsafe extern "C" fn(ctx: *mut c_void) -> *const crate::abi::types::xmlChar>,
284    /// Get the system ID of the current document position.
285    pub getSystemId:
286        Option<unsafe extern "C" fn(ctx: *mut c_void) -> *const crate::abi::types::xmlChar>,
287    /// Get the line number of the current document position.
288    pub getLineNumber: Option<unsafe extern "C" fn(ctx: *mut c_void) -> c_int>,
289    /// Get the column number of the current document position.
290    pub getColumnNumber: Option<unsafe extern "C" fn(ctx: *mut c_void) -> c_int>,
291}
292
293/// Pointer to a SAX locator.
294pub type xmlSAXLocatorPtr = *mut _xmlSAXLocator;
295
296// ═══════════════════════════════════════════════════════════════════════════════
297// Error Callbacks
298// ═══════════════════════════════════════════════════════════════════════════════
299
300/// Structured error handler callback.
301///
302/// Called with a pointer to the error structure. The error structure is valid
303/// only during the callback invocation.
304pub type xmlStructuredErrorFunc = unsafe extern "C" fn(ctx: *mut c_void, error: *const _xmlError);
305
306/// Generic error handler callback (printf-style, variadic at C call site).
307///
308/// # UPSTREAM-PARITY
309///
310/// This is the older error reporting mechanism. New code should use the structured
311/// error handler (`xmlStructuredErrorFunc`) instead.
312pub type xmlGenericErrorFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
313
314// ═══════════════════════════════════════════════════════════════════════════════
315// Validity Callbacks
316// ═══════════════════════════════════════════════════════════════════════════════
317
318/// Validity error handler callback (printf-style, variadic at C call site).
319pub type xmlValidityErrorFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
320
321/// Validity warning handler callback (printf-style, variadic at C call site).
322pub type xmlValidityWarningFunc = unsafe extern "C" fn(ctx: *mut c_void, msg: *const c_char);
323
324// ═══════════════════════════════════════════════════════════════════════════════
325// I/O Callbacks
326// ═══════════════════════════════════════════════════════════════════════════════
327
328/// Read callback for custom input.
329///
330/// Should fill `buffer` with up to `len` bytes.
331/// Returns the number of bytes read, 0 on EOF, or -1 on error.
332pub type xmlInputReadCallback =
333    unsafe extern "C" fn(context: *mut c_void, buffer: *mut c_char, len: c_int) -> c_int;
334
335/// Close callback for custom input.
336///
337/// Returns 0 on success, -1 on error.
338pub type xmlInputCloseCallback = unsafe extern "C" fn(context: *mut c_void) -> c_int;
339
340/// Write callback for custom output.
341///
342/// Should write up to `len` bytes from `buffer`.
343/// Returns the number of bytes written, or -1 on error.
344pub type xmlOutputWriteCallback =
345    unsafe extern "C" fn(context: *mut c_void, buffer: *const c_char, len: c_int) -> c_int;
346
347/// Close callback for custom output.
348///
349/// Returns 0 on success, -1 on error.
350pub type xmlOutputCloseCallback = unsafe extern "C" fn(context: *mut c_void) -> c_int;
351
352// ═══════════════════════════════════════════════════════════════════════════════
353// XPath Callbacks
354// ═══════════════════════════════════════════════════════════════════════════════
355
356/// Variable lookup function for XPath.
357///
358/// Returns an `xmlXPathObjectPtr` representing the variable's value, or NULL.
359///
360/// # UPSTREAM-PARITY
361///
362/// Ownership: The returned object is owned by the caller (must be freed).
363pub type xmlXPathVariableLookupFunc = unsafe extern "C" fn(
364    ctxt: *mut c_void,
365    name: *const crate::abi::types::xmlChar,
366    ns_uri: *const crate::abi::types::xmlChar,
367) -> *mut _xmlXPathObject;
368
369/// Function lookup function for XPath extensions.
370///
371/// Returns a function pointer or NULL.
372pub type xmlXPathFuncLookupFunc = unsafe extern "C" fn(
373    ctxt: *mut c_void,
374    name: *const crate::abi::types::xmlChar,
375    ns_uri: *const crate::abi::types::xmlChar,
376) -> *mut c_void;
377
378// ═══════════════════════════════════════════════════════════════════════════════
379// Resource Loader Callbacks
380// ═══════════════════════════════════════════════════════════════════════════════
381
382/// Resource loader callback.
383///
384/// Loads a resource identified by `url` and returns a parser input.
385///
386/// # UPSTREAM-PARITY
387///
388/// Declared in upstream `parser.h` (2.15+):
389///
390/// ```c
391/// typedef xmlParserErrors
392/// (*xmlResourceLoader)(void *ctxt, const char *url, const char *publicId,
393///                      xmlResourceType type, xmlParserInputFlags flags,
394///                      xmlParserInput **out);
395/// ```
396///
397/// Note: a different, older `void *(*)(const char*, const char*, int, void*)`
398/// signature appears in very old libxml2 headers; the 2.15 contract wins.
399pub type xmlResourceLoader = unsafe extern "C" fn(
400    ctxt: *mut c_void,
401    url: *const c_char,
402    publicId: *const c_char,
403    type_: c_int, // xmlResourceType
404    flags: c_int, // xmlParserInputFlags
405    out: *mut *mut _xmlParserInput,
406) -> c_int; // xmlParserErrors
407
408// ═══════════════════════════════════════════════════════════════════════════════
409// Encoding Callbacks
410// ═══════════════════════════════════════════════════════════════════════════════
411
412/// Character encoding input conversion function.
413///
414/// Converts from the handler's input encoding to UTF-8.
415/// `in` and `inlen` describe input; `out` and `outlen` describe output buffer.
416/// Returns the number of bytes written, or -1 on error.
417pub type xmlCharEncodingInputFunc = unsafe extern "C" fn(
418    out: *mut c_uchar,
419    outlen: *mut c_int,
420    in_: *const c_uchar,
421    inlen: *mut c_int,
422) -> c_int;
423
424/// Modern character encoding conversion function (upstream encoding.h).
425///
426/// ```c
427/// typedef xmlCharEncError
428/// (*xmlCharEncConvFunc)(void *vctxt, unsigned char *out, int *outlen,
429///                       const unsigned char *in, int *inlen, int flush);
430/// ```
431pub type xmlCharEncConvFunc = unsafe extern "C" fn(
432    vctxt: *mut c_void,
433    out: *mut c_uchar,
434    outlen: *mut c_int,
435    in_: *const c_uchar,
436    inlen: *mut c_int,
437    flush: c_int,
438) -> c_int; // xmlCharEncError
439
440/// Conversion-context destructor (upstream encoding.h).
441///
442/// ```c
443/// typedef void (*xmlCharEncConvCtxtDtor)(void *vctxt);
444/// ```
445pub type xmlCharEncConvCtxtDtor = unsafe extern "C" fn(vctxt: *mut c_void);
446
447/// Character encoding output conversion function.
448///
449/// Converts from UTF-8 to the handler's output encoding.
450/// `in` and `inlen` describe input; `out` and `outlen` describe output buffer.
451/// Returns the number of bytes written, or -1 on error.
452pub type xmlCharEncodingOutputFunc = unsafe extern "C" fn(
453    out: *mut c_uchar,
454    outlen: *mut c_int,
455    in_: *const c_uchar,
456    inlen: *mut c_int,
457) -> c_int;
458
459/// Character encoding conversion implementation.
460///
461/// # UPSTREAM-PARITY
462///
463/// Declared in upstream `encoding.h` (2.15+):
464///
465/// ```c
466/// typedef xmlParserErrors
467/// (*xmlCharEncConvImpl)(void *vctxt, const char *name, xmlCharEncFlags flags,
468///                       xmlCharEncodingHandler **out);
469/// ```
470///
471/// Returns an xmlParserErrors code; `out` receives a new handler on success.
472pub type xmlCharEncConvImpl = unsafe extern "C" fn(
473    vctxt: *mut c_void,
474    name: *const c_char,
475    flags: c_int, // xmlCharEncFlags
476    out: *mut *mut crate::abi::structs::_xmlCharEncodingHandler,
477) -> c_int; // xmlParserErrors
478
479// ═══════════════════════════════════════════════════════════════════════════════
480// Catalog Callbacks
481// ═══════════════════════════════════════════════════════════════════════════════
482
483/// Catalog preference callback.
484///
485/// Returns 1 if the system prefers XML catalogs, 0 otherwise.
486pub type xmlCatalogPreferFunc = unsafe extern "C" fn() -> c_int;
487
488// ═══════════════════════════════════════════════════════════════════════════════
489// Allocator Callback Types
490// ═══════════════════════════════════════════════════════════════════════════════
491
492/// Free function type for allocator hooks.
493pub type xmlFreeFunc = unsafe extern "C" fn(ptr: *mut c_void);
494
495/// Malloc function type for allocator hooks.
496pub type xmlMallocFunc = unsafe extern "C" fn(size: usize) -> *mut c_void;
497
498/// Realloc function type for allocator hooks.
499pub type xmlReallocFunc = unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void;
500
501/// Strdup function type for allocator hooks.
502pub type xmlStrdupFunc = unsafe extern "C" fn(str: *const c_char) -> *mut c_void;
503
504// ═══════════════════════════════════════════════════════════════════════════════
505// Module Callbacks
506// ═══════════════════════════════════════════════════════════════════════════════
507
508/// Module register/unregister callback.
509pub type xmlModuleRegisterFunc = unsafe extern "C" fn(module: *mut c_void) -> c_int;
510
511// ═══════════════════════════════════════════════════════════════════════════════
512// Pattern Callbacks
513// ═══════════════════════════════════════════════════════════════════════════════
514
515/// Stream callback for pattern matching.
516pub type xmlStreamCtxtPtr = *mut c_void;
517
518// ═══════════════════════════════════════════════════════════════════════════════
519// Hash Table Callbacks
520// ═══════════════════════════════════════════════════════════════════════════════
521
522/// Deallocator function for hash table entries.
523///
524/// Called when removing an entry from a hash table.
525/// The function receives the payload and the name (key) of the entry.
526pub type xmlHashDeallocator =
527    unsafe extern "C" fn(payload: *mut c_void, name: *mut crate::abi::types::xmlChar);
528
529/// Copier function for hash table entries.
530///
531/// Called when copying a hash table. Returns a copy of the payload.
532pub type xmlHashCopier = unsafe extern "C" fn(
533    payload: *mut c_void,
534    name: *const crate::abi::types::xmlChar,
535) -> *mut c_void;
536
537/// Scanner function for hash table entries.
538///
539/// Called for each entry during xmlHashScan.
540pub type xmlHashScanner = unsafe extern "C" fn(
541    payload: *mut c_void,
542    data: *mut c_void,
543    name: *const crate::abi::types::xmlChar,
544);
545
546/// Full scanner function for hash table entries.
547///
548/// Called for each entry during xmlHashScanFull. Includes all three key parts.
549pub type xmlHashScannerFull = unsafe extern "C" fn(
550    payload: *mut c_void,
551    data: *mut c_void,
552    name: *const crate::abi::types::xmlChar,
553    name2: *const crate::abi::types::xmlChar,
554    name3: *const crate::abi::types::xmlChar,
555);