mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-27 03:27:21 -06:00
M12: doc comments for the functions around this change
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user