adf/lib.rs
1//! Lightweight ADF-XML parsing and writing.
2//!
3//! The crate exposes a domain model for ADF 1.0 while retaining the original
4//! input for byte-for-byte output when a document has not been rewritten.
5//!
6//! # Tracing and privacy
7//!
8//! This crate emits passive [`tracing`] spans and events around parsing,
9//! validation, and writing. It does not install a subscriber; applications
10//! choose how to collect or ignore those events.
11//!
12//! Trace fields intentionally contain only structural metadata such as byte
13//! counts, model counts, dirty flags, validation issue counts, parse options,
14//! and error categories/positions. They do not include raw XML, element text,
15//! attribute values, validation messages, names, emails, phone numbers,
16//! addresses, identifiers, URLs, comments, or extension payloads.
17//!
18//! The public model and [`AdfDocument::original`] still expose lead payloads;
19//! avoid logging those values directly when handling sensitive data.
20
21mod document;
22mod error;
23mod model;
24mod parse;
25mod trace;
26mod validate;
27mod write;
28
29pub use document::{AdfDocument, Attribute, Span, XmlElement, XmlNode};
30pub use error::{Error, Result};
31pub use model::*;
32pub use parse::{DEFAULT_MAX_DOCTYPE_LEN, ParseOptions};
33pub use validate::{
34 Severity, ValidationIssue, ValidationOptions, ValidationReport, validate, validate_with,
35};
36
37/// Parse an ADF-XML document with the default [`ParseOptions`].
38///
39/// Inputs must be well-formed XML rooted at `<adf>`. Other ADF-specific
40/// validation is intentionally separate and can be requested through
41/// [`AdfDocument::validate`].
42///
43/// External and custom entities are never resolved or expanded: the parser
44/// only substitutes the five predefined XML entities and legal numeric
45/// character references. Unknown entity references in text are retained as
46/// [`TextPart::EntityRef`]; unknown entity references in attributes are kept as
47/// literal `&name;` text because [`Attribute`] stores a flat string. By default
48/// a `<!DOCTYPE …>` declaration is preserved but its payload is capped at
49/// [`DEFAULT_MAX_DOCTYPE_LEN`] bytes; use [`parse_with`] to reject DOCTYPEs
50/// outright or to change the limit.
51pub fn parse(input: &str) -> Result<AdfDocument<'_>> {
52 parse::parse(input)
53}
54
55/// Parse an ADF-XML document with explicit [`ParseOptions`].
56///
57/// See [`parse`] for the entity-handling guarantees that apply regardless of
58/// options.
59pub fn parse_with<'a>(input: &'a str, options: &ParseOptions) -> Result<AdfDocument<'a>> {
60 parse::parse_with(input, options)
61}