README

bobzhang/docx2html/opc does not have a README file

#
PackageBuildError

pub(all) suberror PackageBuildError {
PackageBuildError(String)
PackageLimitExceeded(kind~ : String, limit~ : Int64, actual~ : Int64)
} derive(Eq)

A package that cannot be built as specified. PackageBuildError carries a caller-facing message naming the offending part/relationship; PackageLimitExceeded is the TYPED resource-limit refusal from build_limited — it survives to the office transaction layer as a machine-readable ceiling breach (kind ∈ output_bytes / entries / entry_uncompressed_bytes / total_uncompressed_bytes) rather than being flattened into a string.

#
PackageBuildError::equal

#deprecated("implicit trait-method promotion is being removed; call via the trait")
fn PackageBuildError::equal(PackageBuildError, PackageBuildError) -> Bool

#
PackageBuildError::not_equal

#deprecated("implicit trait-method promotion is being removed; call via the trait")
fn PackageBuildError::not_equal(x : PackageBuildError, y : PackageBuildError) -> Bool

#
PackageBuildError::output

#deprecated("implicit trait-method promotion is being removed; call via the trait")
fn PackageBuildError::output(self : PackageBuildError, logger : &Logger) -> Unit

#
PackageBuildError::to_string

#deprecated("implicit trait-method promotion is being removed; call via the trait")
fn PackageBuildError::to_string(self : PackageBuildError) -> String

#
DocxValidationReport

pub struct DocxValidationReport {
// private fields
}

A bounded structural-validation result. Findings remain suitable for humans; resource_limit is the authoritative machine classification.

#
DocxValidationReport::findings

fn DocxValidationReport::findings(self : DocxValidationReport) -> Array[String]

Returns a defensive copy of the bounded human-readable findings.

#
DocxValidationReport::findings_truncated

fn DocxValidationReport::findings_truncated(self : DocxValidationReport) -> Bool

Reports whether validation stopped at the caller's finding-count ceiling.

#
DocxValidationReport::main_document_part

fn DocxValidationReport::main_document_part(self : DocxValidationReport) -> String?

Returns the exact physical archive entry selected by the validated package-root officeDocument relationship. Callers that subsequently parse the package should pin their reader to this identity so validation and interpretation cannot diverge.

#
DocxValidationReport::resource_limit

Returns the ZIP or XML resource guard that stopped validation, when present.

#
DocxValidationResourceLimit

pub(all) enum DocxValidationResourceLimit {
ZipPackageBytes
ZipEntries
ZipEntryUncompressedBytes
ZipTotalUncompressedBytes
ZipTotalPreservedSourceBytes
ZipEntryNameCharacters
ZipTotalEntryNameCharacters
XmlSourceUnits
XmlTokens
XmlTokenLength
XmlMaterializedCharacters
XmlNestingDepth
}

The resource guard that stopped structural validation. This status is kept separate from rendered findings so attacker-controlled part names cannot forge or hide resource exhaustion by changing diagnostic text.

#
DocxValidationResourceLimit::name

Returns the stable machine name for this resource guard.

#
PackageBuilder

pub struct PackageBuilder {
// private fields
}

Assembles an OPC package. State is private — mutate only through the add_* methods. build() emits [Content_Types].xml, then every relationships part, then the parts in insertion order.

#
PackageBuilder::add_default

fn PackageBuilder::add_default(self : PackageBuilder, extension : String, content_type : String) -> Unit raise PackageBuildError

Registers an extension default (xml → content type).

#
PackageBuilder::add_override

fn PackageBuilder::add_override(self : PackageBuilder, part_name : String, content_type : String) -> Unit raise PackageBuildError

Registers a content-type override. part_name is pack-form and must start with / (/word/document.xml).

#
PackageBuilder::add_part

fn PackageBuilder::add_part(self : PackageBuilder, name : String, data : Bytes) -> Unit raise PackageBuildError

Adds a part by logical OPC name (word/document.xml, no leading slash). The builder maps non-ASCII scalars to their ASCII ZIP item spelling at serialization time. Malformed, reserved (builder-emitted), or duplicate names raise.

#
PackageBuilder::add_relationship

fn PackageBuilder::add_relationship(self : PackageBuilder, id : String, relationship_type : String, target : String, source? : String, external? : Bool) -> Unit raise PackageBuildError

Adds a relationship. source~ is the part the relationship belongs to ("" = the package root _rels/.rels); target is source-relative (or pack-absolute with a leading /). Ids must be unique per source. external~ marks a TargetMode="External" relationship (e.g. a hyperlink URL). Id, Type, and Target are normalized to their XML Schema value spaces; external targets are exempt from internal-target resolution.

#
PackageBuilder::build

fn PackageBuilder::build(self : PackageBuilder) -> Bytes raise PackageBuildError

Emits the package bytes. Everything is re-validated here from the authoritative state: part names (shape, reserved, duplicates — including collisions with the builder's own emitted rels parts), content-type coverage for every emitted entry, override targets, relationship sources AND internal targets, and metadata well-formedness. Output is deterministic for a given call sequence.

#
PackageBuilder::build_limited

fn PackageBuilder::build_limited(self : PackageBuilder, limits : PackageLimits) -> Bytes raise PackageBuildError

Like build(), but enforces the given resource ceilings BEFORE the archive payloads are copied/compressed. Over-limit packages raise a typed PackageLimitExceeded (never a flattened string), so callers can map the breach to a machine-readable transaction refusal.

#
PackageBuilder::new

An empty builder: no parts, no content types, no relationships.

#
PackageLimits

pub(all) struct PackageLimits {
max_output_bytes : Int
max_entries : Int
max_entry_uncompressed_bytes : Int
max_total_uncompressed_bytes : Int
}

Pre-allocation ceilings for PackageBuilder::build_limited, mirroring the four TransactionBudget dimensions. Every bound is checked BEFORE the package archive materializes its (potentially large) entry payloads.

#
PartNameConflict

pub(all) enum PartNameConflict {
Equivalent(String)
Derivable(String)
}

The collision reported while registering a logical OPC PartName.

#
PartNameRegistry

pub struct PartNameRegistry {
// private fields
}

A segment trie for OPC PartName identity and non-derivability checks. Storage and work are linear in aggregate PartName length; in particular, a deeply segmented ZIP name never materializes every growing prefix.

#
PartNameRegistry::new

Creates an empty PartName registry.

#
PartNameRegistry::register

fn PartNameRegistry::register(self : PartNameRegistry, name : StringView, display : String) -> PartNameConflict?

Registers name, using display in any returned conflict. Identity is ASCII-case-insensitive and a name conflicts when either side is derivable from the other by appending one or more path segments.

#
is_relationship_part_name

fn is_relationship_part_name(name : String) -> Bool

Returns whether the last two path segments have the reserved OPC Relationships-part shape. A .rels suffix elsewhere is an ordinary part.

#
is_valid_content_type_extension

fn is_valid_content_type_extension(value : String) -> Bool

ECMA-376 Part 2 ST_Extension. A percent sign is legal only as a complete percent-encoded byte; dots and non-ASCII characters are not extension data.

#
is_valid_part_segment

fn is_valid_part_segment(segment : StringView) -> Bool

Reports whether one logical OPC part-name segment is a canonical IRI segment. Literal RFC 3987 ucschar values are valid. Percent escapes must be complete, must not encode / or \\, and must not encode an iunreserved character, including a non-ASCII scalar such as é. OPC also forbids a segment whose final character is ..

#
logical_part_name_from_zip_item_name

fn logical_part_name_from_zip_item_name(name : StringView) -> String?

Maps an ASCII ZIP item name to its logical OPC part name (without the leading slash used by the abstract syntax). Physical ZIP names percent- encode non-ASCII scalars; logical part names contain those scalars literally. Returns None for directory records, reserved metadata, and physical names that do not map to a canonical part name.

#
part_name_key

fn part_name_key(name : StringView) -> String

Returns the OPC logical-identity key. Part and logical-item equivalence is ASCII-case-insensitive only; non-ASCII scalars remain case-sensitive.

#
read_opc_relationships_string_encoded_limited

Strictly parses one already-decoded OPC Relationships part, verifies its XML encoding declaration, and applies Markup Compatibility with only the package Relationships namespace understood. Schema validation remains the caller's responsibility.

#
read_opc_relationships_xml_limited

Strictly parses one OPC Relationships part and applies Markup Compatibility with only the package Relationships namespace understood. Schema validation remains the caller's responsibility.

#
read_opc_relationships_xml_with_roots_limited

Parses one OPC Relationships part and returns both its raw XML tree and its MCE-effective tree from one bounded parse. Byte-preserving mutation uses the raw projection to reject compatibility-dependent edits before splicing.

#
relationship_source_part_name

fn relationship_source_part_name(name : String) -> String?

Derives the package-root or part source represented by a Relationships-part name. Only the final _rels/<filename>.rels pair is structural; earlier _rels segments belong to the source PartName.

#
relationships_part_name_for_source

fn relationships_part_name_for_source(source : String) -> String

Returns the logical Relationships-part name for a package-root or part source. Earlier _rels path segments remain ordinary source-name segments.

#
resolve_part_target

fn resolve_part_target(base : String, target : StringView) -> String?

Resolves an internal OPC relationship target and rejects any result that is not a canonical logical PartName. This boundary deliberately operates on IRIs, not physical ZIP item names.

#
resolve_target

fn resolve_target(base : String, target : String) -> String?

Resolves one internal relationship target against an archive-directory base. Package-rooted targets (/word/media/x.png) and relative targets use the same dot-segment normalization. Empty segments, URI schemes, query/fragment text, backslashes, empty results, and any traversal above the package root fail closed instead of being silently clamped.

#
validate_docx_archive

fn validate_docx_archive(archive :
Archive
) -> Array[String]

Validates an already materialized DOCX archive without reading or inflating the package again. The caller retains ownership; validation is read-only.

#
validate_docx_archive_limited

fn validate_docx_archive_limited(archive :
Archive
, max_findings~ : Int, max_message_chars~ : Int, max_zip_entry_name_chars? : Int, max_zip_total_entry_name_chars? : Int, max_xml_source_units? : Int, max_xml_tokens? : Int, max_xml_materialized_chars? : Int, max_xml_token_chars? : Int, cancelled? : () -> Bool) -> (Array[String], Bool)

Archive-backed validation with a hard finding count and per-message scalar ceiling applied during production rather than after an unbounded array is built.

#
validate_docx_archive_report_limited

fn validate_docx_archive_report_limited(archive :
Archive
, max_findings~ : Int, max_message_chars~ : Int, max_zip_entry_name_chars? : Int, max_zip_total_entry_name_chars? : Int, max_xml_source_units? : Int, max_xml_tokens? : Int, max_xml_materialized_chars? : Int, max_xml_token_chars? : Int, cancelled? : () -> Bool) -> DocxValidationReport

Archive-backed validation with typed resource-exhaustion status preserved independently of bounded human findings.

#
validate_docx_package

fn validate_docx_package(data : BytesView) -> Array[String]

Validates docx package structure. Returns bounded findings; empty = valid.

#
validate_docx_package_limited

fn validate_docx_package_limited(data : BytesView, max_findings~ : Int, max_message_chars~ : Int, max_zip_package_bytes? : Int, max_zip_entries? : Int, max_zip_entry_uncompressed_bytes? : Int, max_zip_total_uncompressed_bytes? : Int, max_zip_total_preserved_source_bytes? : Int, max_zip_entry_name_chars? : Int, max_zip_total_entry_name_chars? : Int, max_xml_source_units? : Int, max_xml_tokens? : Int, max_xml_materialized_chars? : Int, max_xml_token_chars? : Int) -> (Array[String], Bool)

Validates package bytes while bounding findings as they are produced. truncated=true means validation stopped after filling the caller's cap.

#
validate_docx_package_report_limited

fn validate_docx_package_report_limited(data : BytesView, max_findings~ : Int, max_message_chars~ : Int, max_zip_package_bytes? : Int, max_zip_entries? : Int, max_zip_entry_uncompressed_bytes? : Int, max_zip_total_uncompressed_bytes? : Int, max_zip_total_preserved_source_bytes? : Int, max_zip_entry_name_chars? : Int, max_zip_total_entry_name_chars? : Int, max_xml_source_units? : Int, max_xml_tokens? : Int, max_xml_materialized_chars? : Int, max_xml_token_chars? : Int) -> DocxValidationReport

The typed counterpart to validate_docx_package_limited. Resource status is captured from the ZIP/XML error before any attacker-controlled text is interpolated or truncated into a finding.

#
zip_item_name_from_logical_part_name

fn zip_item_name_from_logical_part_name(name : StringView) -> String?

Maps a canonical logical OPC part name (without its leading slash) to the ASCII ZIP item spelling required by ECMA-376. Existing legal percent escapes remain intact; every literal non-ASCII scalar is UTF-8 percent- encoded with uppercase hexadecimal digits.