M12: doc comments for the functions around this change

This commit is contained in:
Eric Kaden
2026-10-20 09:25:19 -04:00
parent 5cd7e816b9
commit f9daeeb1fa
3 changed files with 24 additions and 0 deletions
+2
View File
@@ -96,6 +96,8 @@ pub fn static_shell(data: &str) -> Vec<u8> {
assemble(objs)
}
/// A PDF file holding `objs` as objects 1, 2, … in order, with a cross-reference table and a
/// trailer whose root is object 1.
fn assemble(objs: Vec<Vec<u8>>) -> Vec<u8> {
let mut out = b"%PDF-1.7\n".to_vec();
let mut offsets = Vec::new();
+4
View File
@@ -186,6 +186,9 @@ impl Walker<'_> {
true
}
/// Record the scripts of the object at `som` as events: each non-empty event script, then its
/// calculate and validate scripts (the validate one with `message`). Once [`MAX_EVENTS`] events
/// are recorded, nothing more is and the form is marked truncated.
fn push_events(&mut self, som: &str, scripts: &[Script], calculate: Option<&Script>, validate: Option<&Script>, message: Option<&str>) {
if self.events.len() >= MAX_EVENTS {
self.truncated = true;
@@ -233,6 +236,7 @@ impl Walker<'_> {
name.and_then(|_| self.ov.presence.get(som)).cloned().unwrap_or_else(|| presence_name(p).to_string())
}
/// The access of the object at `som`: a script's, or else the template's `a`.
fn access(&self, som: &str, a: Access) -> String {
self.ov.access.get(som).cloned().unwrap_or_else(|| access_name(a).to_string())
}
+18
View File
@@ -539,6 +539,9 @@ fn xfa_bytes(doc: &Document) -> Vec<u8> {
s.decoded_within(1 << 20).unwrap()
}
/// Writing field values into the datasets keeps every data node no field binds to as written,
/// changes the bound values in place and adds a missing one beside them. Writing the same values
/// again changes nothing, and a field bound to structured content is reported, not flattened.
#[test]
fn writing_values_keeps_the_data_no_field_binds_to() {
// Regression: the data element was rebuilt from the fields alone, dropping everything else.
@@ -579,6 +582,9 @@ fn writing_values_keeps_the_data_no_field_binds_to() {
assert!(String::from_utf8(xfa_bytes(&doc)).unwrap().contains("<name><p>rich</p></name>"));
}
/// A UTF-16 packet in either byte order, with a byte order mark, has its values read exactly and
/// is written back as UTF-16 with its mark. A packet in neither UTF-8 nor UTF-16 is left alone,
/// and that is reported.
#[test]
fn utf16_packets_are_read_and_written_back_as_utf16() {
let mut doc = Document::open(Arc::new(static_shell("<form1><page1><name>Zoë 日本</name><other>ünbound</other></page1></form1>"))).unwrap();
@@ -608,6 +614,9 @@ fn utf16_packets_are_read_and_written_back_as_utf16() {
assert_eq!(xfa_bytes(&doc), latin1);
}
/// Hundreds of fields with absurd SOM indices finish within seconds, both writing the datasets and
/// building fresh data, create at most the node budget and report what they could not write. A
/// moderate index still works, creating the empty instances before it.
#[test]
fn huge_som_indices_are_capped_not_built() {
// Regression: each index created its missing siblings one count at a time (quadratic), with
@@ -647,6 +656,9 @@ fn huge_som_indices_are_capped_not_built() {
assert!(d.get(&som_to_path("form1[0].row[2]")).is_some(), "the instances in between exist, empty");
}
/// The live form tree carries each object's SOM path, value, presence and access, one instance of
/// a repeating row without data, and the template's event, calculate and validate scripts (FormCalc
/// when no content type is given). Data adds rows and values, and an override changes presence.
#[test]
fn the_form_tree_carries_values_presence_instances_and_the_events() {
let xml = scripted_template();
@@ -681,6 +693,9 @@ fn the_form_tree_carries_values_presence_instances_and_the_events() {
assert_eq!(page.children.iter().find(|c| c.name == "details").unwrap().kind, Some(NodeKind::Subform));
}
/// Presence and access overrides are kept on the AcroForm and applied to the template: `note` has
/// no widget while `details` is hidden and gets one once an override shows it and the form is laid
/// out again. Saving and reopening keeps the overrides and one set of fields; storing none removes the key.
#[test]
fn overrides_live_in_the_acroform_and_hide_objects_in_the_layout() {
let mut doc = Document::open(Arc::new(shell(&scripted_template()))).unwrap();
@@ -739,6 +754,9 @@ fn showing_a_subform_leaves_its_unnamed_hidden_objects_hidden() {
assert_eq!(details.children.iter().find(|c| c.kind == Some(NodeKind::Subform)).map(|c| c.presence.as_str()), Some("hidden"));
}
/// Adding and removing data instances edits the datasets packet, creating it when missing: asking
/// for no more rows than exist, or removing one that is not there, changes nothing, and removing a
/// row moves the later ones up. The layout follows the data, and an absurd count is capped, not built.
#[test]
fn data_instances_are_added_and_removed_in_the_packet() {
let mut doc = Document::open(Arc::new(shell(&scripted_template()))).unwrap();