aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmulator0002020-09-23 23:01:05 +0200
committerEmulator0002020-09-23 23:01:05 +0200
commitec35be1f2ded5e90bf4dd8bdb8aaa8d76bf84942 (patch)
treea12a9831e152946a15024b53bbd22b2039729cd7
parent0990ddfbdb63a5683d6f94513842dae37166c838 (diff)
downloadpdf_form-ec35be1f2ded5e90bf4dd8bdb8aaa8d76bf84942.tar.bz2
Updated all libraries and a lot of fixes
-rw-r--r--.gitignore4
-rw-r--r--.idea/.gitignore4
-rw-r--r--.idea/modules.xml8
-rw-r--r--.idea/pdf_form.iml12
-rw-r--r--.idea/vcs.xml6
-rw-r--r--Cargo.lock284
-rw-r--r--Cargo.toml21
-rw-r--r--src/lib.rs538
8 files changed, 634 insertions, 243 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a62ab56
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+**/*.rs.bk
+/*.data
+/*.gz
+/target/
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..86730ac
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,4 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+/dbnavigator.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..ad5009c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/pdf_form.iml" filepath="$PROJECT_DIR$/.idea/pdf_form.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/pdf_form.iml b/.idea/pdf_form.iml
new file mode 100644
index 0000000..9b4cf84
--- /dev/null
+++ b/.idea/pdf_form.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <excludeFolder url="file://$MODULE_DIR$/target" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="Git" />
+ </component>
+</project> \ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index e38f374..96dbf72 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,18 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "adler"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "bitflags"
-version = "1.0.3"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -9,17 +21,69 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "cc"
-version = "1.0.17"
+name = "cfg-if"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
-version = "0.3.0"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -34,7 +98,12 @@ dependencies = [
[[package]]
name = "dtoa"
-version = "0.4.2"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "either"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -96,95 +165,134 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "flate2"
-version = "0.2.20"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miniz_oxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
-version = "0.3.4"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
-version = "0.2.42"
+version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "linked-hash-map"
-version = "0.3.0"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "lopdf"
-version = "0.15.2"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "pom 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pom 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "miniz-sys"
-version = "0.1.10"
+name = "lzw"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memoffset"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "num"
-version = "0.1.42"
+name = "miniz_oxide"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
-version = "0.1.38"
+version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "num-iter"
-version = "0.1.37"
+name = "num-traits"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "num-traits"
-version = "0.2.4"
+name = "num_cpus"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
-name = "pdf_form"
+name = "pdf_forms"
version = "0.1.0"
dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "lopdf 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lopdf 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pom"
-version = "1.1.0"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -193,8 +301,31 @@ version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "redox_syscall"
-version = "0.1.40"
+name = "rayon"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon-core 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -217,12 +348,12 @@ dependencies = [
[[package]]
name = "time"
-version = "0.1.40"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -231,8 +362,13 @@ version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "winapi"
-version = "0.3.5"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -250,12 +386,20 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
-"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
+"checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
+"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum case 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e88b166b48e29667f5443df64df3c61dc07dc2b1a0b0d231800e07f09a33ecc1"
-"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
-"checksum chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e"
+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+"checksum chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
+"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+"checksum crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
+"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
+"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
+"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
"checksum derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ec098440b29ea3b1ece3e641bac424c19cf996779b623c9e0f2171495425c2c8"
-"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
+"checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
+"checksum either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
@@ -263,23 +407,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
-"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
-"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
-"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1"
-"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
-"checksum lopdf 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4777bc707e21e9f1a3aed4da3b3a711a7eb468963df3c077fe48409993c1ae9"
-"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
-"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
-"checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45"
-"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
-"checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
-"checksum pom 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60f6ce597ecdcc9a098e7fddacb1065093a3d66446fa16c675e7e71d1b5c28e6"
+"checksum flate2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "766d0e77a2c1502169d4a93ff3b8c15a71fd946cd0126309752104e5f3c46d94"
+"checksum hermit-abi 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
+"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+"checksum libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
+"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939"
+"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
+"checksum lopdf 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3170bf7b90ea1fc3c4eaa1bed4882dddcfd58b79baa60fd1e10829a482f464f9"
+"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
+"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+"checksum memoffset 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
+"checksum miniz_oxide 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9"
+"checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
+"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
+"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+"checksum pom 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e2192780e9f8e282049ff9bffcaa28171e1cb0844f49ed5374e518ae6024ec"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
+"checksum rayon 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd016f0c045ad38b5251be2c9c0ab806917f82da4d36b2a327e5166adad9270"
+"checksum rayon-core 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf"
+"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
+"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
-"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
+"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 271f7a7..0455e89 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,13 +1,14 @@
[package]
-name = "pdf_form"
-version = "0.2.0"
-authors = ["Jake <jsandler18@gmail.com>"]
-readme = "README.md"
-keywords = ["pdf", "form"]
-description = "A library for programatically filling out pdf forms"
-license = "MIT"
+ name = "pdf_forms"
+ version = "0.1.0"
+ authors = ["Jake <jsandler18@gmail.com>", "Malte <voos.malte@gmail.com>", "Emulator000 <emulator@hotmail.it"]
+ description = "A library for programatically filling out pdf forms"
+ edition = "2018"
+ readme = "README.md"
+ keywords = ["pdf", "form", "forms", "field"]
+ license = "MIT"
[dependencies]
-lopdf = "0.15.1"
-bitflags = "1.0.1"
-derive-error = "0.0.4"
+ bitflags = "^1.2"
+ derive-error = "^0.0.4"
+ lopdf = "^0.25"
diff --git a/src/lib.rs b/src/lib.rs
index 3f1e1c4..670f3ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,16 +1,17 @@
-//! This crate is for filling out PDFs with forms programatically.
-extern crate lopdf;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate derive_error;
-use lopdf::{Document, ObjectId, Object, StringFormat};
-use std::path::Path;
use std::collections::VecDeque;
use std::io;
+use std::io::Write;
+use std::path::Path;
use std::str;
+use bitflags::_core::str::from_utf8;
+use lopdf::{Document, Object, ObjectId, StringFormat};
+
bitflags! {
struct ButtonFlags: u32 {
const NO_TOGGLE_TO_OFF = 0x8000;
@@ -23,10 +24,10 @@ bitflags! {
bitflags! {
struct ChoiceFlags: u32 {
- const COBMO = 0x40000;
- const EDIT = 0x80000;
- const SORT = 0x100000;
- const MULTISELECT = 0x400000;
+ const COBMO = 0x20000;
+ const EDIT = 0x40000;
+ const SORT = 0x80000;
+ const MULTISELECT = 0x200000;
const DO_NOT_SPELLCHECK = 0x800000;
const COMMIT_ON_CHANGE = 0x8000000;
}
@@ -38,8 +39,8 @@ bitflags! {
/// analyze the PDF and identify the fields. Then you can get and set the content of the fields by
/// index.
pub struct Form {
- doc: Document,
- form_ids: Vec<ObjectId>
+ doc: Document,
+ form_ids: Vec<ObjectId>,
}
/// The possible types of fillable form fields in a PDF
@@ -50,7 +51,7 @@ pub enum FieldType {
CheckBox,
ListBox,
ComboBox,
- Text
+ Text,
}
/// The current state of a form field
@@ -58,32 +59,39 @@ pub enum FieldType {
pub enum FieldState {
/// Push buttons have no state
Button,
- /// `selected` is the sigular option from `options` that is selected
- Radio { selected: String, options: Vec<String> },
+ /// `selected` is the singular option from `options` that is selected
+ Radio {
+ selected: String,
+ options: Vec<String>,
+ },
/// The toggle state of the checkbox
CheckBox { is_checked: bool },
/// `selected` is the list of selected options from `options`
- ListBox { selected: Vec<String>, options: Vec<String>, multiselect: bool },
+ ListBox {
+ selected: Vec<String>,
+ options: Vec<String>,
+ multiselect: bool,
+ },
/// `selected` is the list of selected options from `options`
- ComboBox { selected: Vec<String>, options: Vec<String>, multiselect: bool },
+ ComboBox {
+ selected: Vec<String>,
+ options: Vec<String>,
+ editable: bool,
+ },
/// User Text Input
- Text { text: String }
+ Text { text: String },
}
#[derive(Debug, Error)]
/// Errors that may occur while loading a PDF
pub enum LoadError {
- /// An IO Error
- IoError(io::Error),
- /// A dictionary key that must be present in order to find forms was not present
- DictionaryKeyNotFound,
+ /// An Lopdf Error
+ LopdfError(lopdf::Error),
/// The reference `ObjectId` did not point to any values
#[error(non_std, no_from)]
NoSuchReference(ObjectId),
/// An element that was expected to be a reference was not a reference
NotAReference,
- /// A value that must be a certain type was not that type
- UnexpectedType
}
/// Errors That may occur while setting values in a form
@@ -94,7 +102,7 @@ pub enum ValueError {
/// One or more selected values are not valid choices
InvalidSelection,
/// Multiple values were selected when only one was allowed
- TooManySelected
+ TooManySelected,
}
trait PdfObjectDeref {
@@ -105,13 +113,12 @@ impl PdfObjectDeref for Object {
fn deref<'a>(&self, doc: &'a Document) -> Result<&'a Object, LoadError> {
match self {
&Object::Reference(oid) => doc.objects.get(&oid).ok_or(LoadError::NoSuchReference(oid)),
- _ => Err(LoadError::NotAReference)
+ _ => Err(LoadError::NotAReference),
}
}
}
impl Form {
-
/// Takes a reader containing a PDF with a fillable form, analyzes the content, and attempts to
/// identify all of the fields the form has.
pub fn load_from<R: io::Read>(reader: R) -> Result<Self, LoadError> {
@@ -126,24 +133,18 @@ impl Form {
Self::load_doc(doc)
}
- fn load_doc(doc: Document) -> Result<Self, LoadError>{
+ fn load_doc(doc: Document) -> Result<Self, LoadError> {
let mut form_ids = Vec::new();
let mut queue = VecDeque::new();
// Block so borrow of doc ends before doc is moved into the result
{
// Get the form's top level fields
- let catalog = doc.trailer.get("Root")
- .ok_or(LoadError::DictionaryKeyNotFound)?
- .deref(&doc)?
- .as_dict().ok_or(LoadError::UnexpectedType)?;
- let acroform = catalog.get("AcroForm")
- .ok_or(LoadError::DictionaryKeyNotFound)?
- .deref(&doc)?
- .as_dict().ok_or(LoadError::UnexpectedType)?;
- let fields_list = acroform.get("Fields")
- .ok_or(LoadError::DictionaryKeyNotFound)?
- // .deref(&doc)?
- .as_array().ok_or(LoadError::UnexpectedType)?;
+ let catalog = doc.trailer.get(b"Root")?.deref(&doc)?.as_dict()?;
+ let acroform = catalog.get(b"AcroForm")?.deref(&doc)?.as_dict()?;
+ let fields_list = acroform
+ .get(b"Fields")?
+ // .deref(&doc)?
+ .as_array()?;
queue.append(&mut VecDeque::from(fields_list.clone()));
// Iterate over the fields
@@ -151,11 +152,12 @@ impl Form {
let obj = objref.deref(&doc)?;
if let &Object::Dictionary(ref dict) = obj {
// If the field has FT, it actually takes input. Save this
- if let Some(_) = dict.get("FT") {
+ if let Ok(_) = dict.get(b"FT") {
form_ids.push(objref.as_reference().unwrap());
}
+
// If this field has kids, they might have FT, so add them to the queue
- if let Some(&Object::Array(ref kids)) = dict.get("Kids") {
+ if let Ok(&Object::Array(ref kids)) = dict.get(b"Kids") {
queue.append(&mut VecDeque::from(kids.clone()));
}
}
@@ -166,7 +168,7 @@ impl Form {
/// Returns the number of fields the form has
pub fn len(&self) -> usize {
- self.form_ids.len()
+ self.form_ids.len()
}
/// Gets the type of field of the given index
@@ -175,12 +177,20 @@ impl Form {
/// This function will panic if the index is greater than the number of fields
pub fn get_type(&self, n: usize) -> FieldType {
// unwraps should be fine because load should have verified everything exists
- let field = self.doc.objects.get(&self.form_ids[n]).unwrap().as_dict().unwrap();
+ let field = self
+ .doc
+ .objects
+ .get(&self.form_ids[n])
+ .unwrap()
+ .as_dict()
+ .unwrap();
let obj_zero = Object::Integer(0);
- let type_str = field.get("FT").unwrap().as_name_str().unwrap();
+ let type_str = field.get(b"FT").unwrap().as_name_str().unwrap();
if type_str == "Btn" {
- let flags = ButtonFlags::from_bits_truncate(field.get("Ff").unwrap_or(&obj_zero).as_i64().unwrap() as u32);
- if flags.intersects(ButtonFlags::RADIO) {
+ let flags = ButtonFlags::from_bits_truncate(
+ field.get(b"Ff").unwrap_or(&obj_zero).as_i64().unwrap() as u32,
+ );
+ if flags.intersects(ButtonFlags::RADIO | ButtonFlags::NO_TOGGLE_TO_OFF) {
FieldType::Radio
} else if flags.intersects(ButtonFlags::PUSHBUTTON) {
FieldType::Button
@@ -188,7 +198,9 @@ impl Form {
FieldType::CheckBox
}
} else if type_str == "Ch" {
- let flags = ChoiceFlags::from_bits_truncate(field.get("Ff").unwrap_or(&obj_zero).as_i64().unwrap() as u32);
+ let flags = ChoiceFlags::from_bits_truncate(
+ field.get(b"Ff").unwrap_or(&obj_zero).as_i64().unwrap() as u32,
+ );
if flags.intersects(ChoiceFlags::COBMO) {
FieldType::ComboBox
} else {
@@ -199,12 +211,42 @@ impl Form {
}
}
+ /// Gets the name of field of the given index
+ ///
+ /// # Panics
+ /// This function will panic if the index is greater than the number of fields
+ pub fn get_name(&self, n: usize) -> Option<String> {
+ // unwraps should be fine because load should have verified everything exists
+ let field = self
+ .doc
+ .objects
+ .get(&self.form_ids[n])
+ .unwrap()
+ .as_dict()
+ .unwrap();
+
+ // The "T" key refers to the name of the field
+ match field.get(b"T") {
+ Ok(Object::String(data, _)) => String::from_utf8(data.clone()).ok(),
+ _ => None,
+ }
+ }
+
/// Gets the types of all of the fields in the form
pub fn get_all_types(&self) -> Vec<FieldType> {
let mut res = Vec::with_capacity(self.len());
for i in 0..self.len() {
res.push(self.get_type(i))
- };
+ }
+ res
+ }
+
+ /// Gets the names of all of the fields in the form
+ pub fn get_all_names(&self) -> Vec<Option<String>> {
+ let mut res = Vec::with_capacity(self.len());
+ for i in 0..self.len() {
+ res.push(self.get_name(i))
+ }
res
}
@@ -213,150 +255,223 @@ impl Form {
/// # Panics
/// This function will panic if the index is greater than the number of fields
pub fn get_state(&self, n: usize) -> FieldState {
- let field = self.doc.objects.get(&self.form_ids[n]).unwrap().as_dict().unwrap();
+ let field = self
+ .doc
+ .objects
+ .get(&self.form_ids[n])
+ .unwrap()
+ .as_dict()
+ .unwrap();
match self.get_type(n) {
FieldType::Button => FieldState::Button,
FieldType::Radio => FieldState::Radio {
- selected: match field.get("V") {
- Some(name) => name.as_name_str().unwrap().to_owned(),
- None => match field.get("AS") {
- Some(name) => name.as_name_str().unwrap().to_owned(),
- None => "".to_owned()
- }
+ selected: match field.get(b"V") {
+ Ok(name) => name.as_name_str().unwrap().to_owned(),
+ Err(_) => match field.get(b"AS") {
+ Ok(name) => name.as_name_str().unwrap().to_owned(),
+ Err(_) => "".to_owned(),
+ },
},
- options: self.get_possibilities(self.form_ids[n])
+ options: self.get_possibilities(self.form_ids[n]),
},
- FieldType::CheckBox=> FieldState::CheckBox { is_checked:
- match field.get("V") {
- Some(name) => if name.as_name_str().unwrap() == "Yes" { true } else { false },
- None => match field.get("AS") {
- Some(name) => if name.as_name_str().unwrap() == "Yes" { true } else { false },
- None => false
+ FieldType::CheckBox => FieldState::CheckBox {
+ is_checked: match field.get(b"V") {
+ Ok(name) => {
+ if name.as_name_str().unwrap() == "Yes" {
+ true
+ } else {
+ false
+ }
}
- }
+ Err(_) => match field.get(b"AS") {
+ Ok(name) => {
+ if name.as_name_str().unwrap() == "Yes" {
+ true
+ } else {
+ false
+ }
+ }
+ Err(_) => false,
+ },
+ },
},
FieldType::ListBox => FieldState::ListBox {
// V field in a list box can be either text for one option, an array for many
// options, or null
- selected: match field.get("V") {
- Some(selection) => match selection {
- &Object::String(ref s,StringFormat::Literal) => vec![str::from_utf8(&s).unwrap().to_owned()],
+ selected: match field.get(b"V") {
+ Ok(selection) => match selection {
+ &Object::String(ref s, StringFormat::Literal) => {
+ vec![str::from_utf8(&s).unwrap().to_owned()]
+ }
&Object::Array(ref chosen) => {
let mut res = Vec::new();
for obj in chosen {
- if let &Object::String(ref s,StringFormat::Literal) = obj {
+ if let &Object::String(ref s, StringFormat::Literal) = obj {
res.push(str::from_utf8(&s).unwrap().to_owned());
}
}
res
}
- _ => Vec::new()
+ _ => Vec::new(),
},
- None => Vec::new()
+ Err(_) => Vec::new(),
},
// The options is an array of either text elements or arrays where the second
// element is what we want
- options: match field.get("Opt") {
- Some(&Object::Array(ref options)) => options.iter().map(|x| {
- match x {
- &Object::String(ref s,StringFormat::Literal) => str::from_utf8(&s).unwrap().to_owned(),
- &Object::Array(ref arr) => if let &Object::String(ref s,StringFormat::Literal) = &arr[1] {
+ options: match field.get(b"Opt") {
+ Ok(&Object::Array(ref options)) => options
+ .iter()
+ .map(|x| match x {
+ &Object::String(ref s, StringFormat::Literal) => {
str::from_utf8(&s).unwrap().to_owned()
- } else {
- String::new()
- },
- _ => String::new()
- }
- }).filter(|x| x.len() > 0).collect(),
- _ => Vec::new()
+ }
+ &Object::Array(ref arr) => {
+ if let &Object::String(ref s, StringFormat::Literal) = &arr[1] {
+ str::from_utf8(&s).unwrap().to_owned()
+ } else {
+ String::new()
+ }
+ }
+ _ => String::new(),
+ })
+ .filter(|x| x.len() > 0)
+ .collect(),
+ _ => Vec::new(),
},
multiselect: {
-
- let flags = ChoiceFlags::from_bits_truncate(field.get("Ff").unwrap().as_i64().unwrap() as u32);
+ let flags = ChoiceFlags::from_bits_truncate(
+ field
+ .get(b"Ff")
+ .unwrap_or(&Object::Integer(0))
+ .as_i64()
+ .unwrap() as u32,
+ );
flags.intersects(ChoiceFlags::MULTISELECT)
- }
+ },
},
FieldType::ComboBox => FieldState::ComboBox {
// V field in a list box can be either text for one option, an array for many
// options, or null
- selected: match field.get("V") {
- Some(selection) => match selection {
- &Object::String(ref s,StringFormat::Literal) => vec![str::from_utf8(&s).unwrap().to_owned()],
+ selected: match field.get(b"V") {
+ Ok(selection) => match selection {
+ &Object::String(ref s, StringFormat::Literal) => {
+ vec![str::from_utf8(&s).unwrap().to_owned()]
+ }
&Object::Array(ref chosen) => {
let mut res = Vec::new();
for obj in chosen {
- if let &Object::String(ref s,StringFormat::Literal) = obj {
+ if let &Object::String(ref s, StringFormat::Literal) = obj {
res.push(str::from_utf8(&s).unwrap().to_owned());
}
}
res
}
- _ => Vec::new()
+ _ => Vec::new(),
},
- None => Vec::new()
+ Err(_) => Vec::new(),
},
// The options is an array of either text elements or arrays where the second
// element is what we want
- options: match field.get("Opt") {
- Some(&Object::Array(ref options)) => options.iter().map(|x| {
- match x {
- &Object::String(ref s,StringFormat::Literal) => str::from_utf8(&s).unwrap().to_owned(),
- &Object::Array(ref arr) => if let &Object::String(ref s,StringFormat::Literal) = &arr[1] {
+ options: match field.get(b"Opt") {
+ Ok(&Object::Array(ref options)) => options
+ .iter()
+ .map(|x| match x {
+ &Object::String(ref s, StringFormat::Literal) => {
str::from_utf8(&s).unwrap().to_owned()
- } else {
- String::new()
- },
- _ => String::new()
- }
- }).filter(|x| x.len() > 0).collect(),
- _ => Vec::new()
+ }
+ &Object::Array(ref arr) => {
+ if let &Object::String(ref s, StringFormat::Literal) = &arr[1] {
+ str::from_utf8(&s).unwrap().to_owned()
+ } else {
+ String::new()
+ }
+ }
+ _ => String::new(),
+ })
+ .filter(|x| x.len() > 0)
+ .collect(),
+ _ => Vec::new(),
+ },
+ editable: {
+ let flags = ChoiceFlags::from_bits_truncate(
+ field
+ .get(b"Ff")
+ .unwrap_or(&Object::Integer(0))
+ .as_i64()
+ .unwrap() as u32,
+ );
+ flags.intersects(ChoiceFlags::EDIT)
+ },
+ },
+ FieldType::Text => FieldState::Text {
+ text: match field.get(b"V") {
+ Ok(&Object::String(ref s, StringFormat::Literal)) => {
+ str::from_utf8(&s.clone()).unwrap().to_owned()
+ }
+ _ => "".to_owned(),
},
- multiselect: {
-
- let flags = ChoiceFlags::from_bits_truncate(field.get("Ff").unwrap().as_i64().unwrap() as u32);
- flags.intersects(ChoiceFlags::MULTISELECT)
- }
},
- FieldType::Text => FieldState::Text{ text:
- match field.get("V") {
- Some(&Object::String(ref s,StringFormat::Literal)) =>
- str::from_utf8(&s.clone()).unwrap().to_owned(),
- _ => "".to_owned()
- }
-
- }
}
}
-
/// If the field at index `n` is a text field, fills in that field with the text `s`.
/// If it is not a text field, returns ValueError
///
/// # Panics
/// Will panic if n is larger than the number of fields
- pub fn set_text(&mut self, n: usize, s: String) -> Result<(),ValueError> {
+ pub fn set_text(&mut self, n: usize, s: String) -> Result<(), ValueError> {
match self.get_type(n) {
FieldType::Text => {
- let field = self.doc.objects.get_mut(&self.form_ids[n]).unwrap().as_dict_mut().unwrap();
- field.set("V",Object::String(s.into_bytes(),StringFormat::Literal));
- field.remove("AP");
+ let field = self
+ .doc
+ .objects
+ .get_mut(&self.form_ids[n])
+ .unwrap()
+ .as_dict_mut()
+ .unwrap();
+ field.set("V", Object::String(s.into_bytes(), StringFormat::Literal));
+ field.remove(b"AP");
Ok(())
- },
- _ => Err(ValueError::TypeMismatch)
-
+ }
+ _ => Err(ValueError::TypeMismatch),
}
}
fn get_possibilities(&self, oid: ObjectId) -> Vec<String> {
let mut res = Vec::new();
- let kids_obj = self.doc.objects.get(&oid).unwrap().as_dict().unwrap().get("Kids");
- if let Some(&Object::Array(ref kids)) = kids_obj {
- for kid in kids {
- if let Some(&Object::Name(ref s)) = kid.deref(&self.doc).unwrap().as_dict().unwrap().get("AS") {
- res.push(str::from_utf8(&s).unwrap().to_owned());
+ let kids_obj = self
+ .doc
+ .objects
+ .get(&oid)
+ .unwrap()
+ .as_dict()
+ .unwrap()
+ .get(b"Kids");
+ if let Ok(&Object::Array(ref kids)) = kids_obj {
+ for (i, kid) in kids.iter().enumerate() {
+ let mut found = false;
+ if let Ok(&Object::Dictionary(ref appearance_states)) =
+ kid.deref(&self.doc).unwrap().as_dict().unwrap().get(b"AP")
+ {
+ if let Ok(&Object::Dictionary(ref normal_appearance)) =
+ appearance_states.get(b"N")
+ {
+ for (key, _) in normal_appearance {
+ if key != b"Off" {
+ res.push(from_utf8(key).unwrap_or("").to_owned());
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if !found {
+ res.push(i.to_string());
}
}
}
+
res
}
@@ -366,17 +481,32 @@ impl Form {
///
/// # Panics
/// Will panic if n is larger than the number of fields
- pub fn set_check_box(&mut self, n: usize, is_checked: bool) -> Result<(),ValueError> {
+ pub fn set_check_box(&mut self, n: usize, is_checked: bool) -> Result<(), ValueError> {
match self.get_type(n) {
FieldType::CheckBox => {
- let state = Object::Name({if is_checked {"Yes"} else {"Off"}}.to_owned().into_bytes());
- let field = self.doc.objects.get_mut(&self.form_ids[n]).unwrap().as_dict_mut().unwrap();
- field.set("V",state.clone());
- field.set("AS",state);
+ let state = Object::Name(
+ {
+ if is_checked {
+ "Yes"
+ } else {
+ "Off"
+ }
+ }
+ .to_owned()
+ .into_bytes(),
+ );
+ let field = self
+ .doc
+ .objects
+ .get_mut(&self.form_ids[n])
+ .unwrap()
+ .as_dict_mut()
+ .unwrap();
+ field.set("V", state.clone());
+ field.set("AS", state);
Ok(())
- },
- _ => Err(ValueError::TypeMismatch)
-
+ }
+ _ => Err(ValueError::TypeMismatch),
}
}
@@ -386,53 +516,127 @@ impl Form {
///
/// # Panics
/// Will panic if n is larger than the number of fields
- pub fn set_radio(&mut self, n: usize, choice: String) -> Result<(),ValueError> {
+ pub fn set_radio(&mut self, n: usize, choice: String) -> Result<(), ValueError> {
match self.get_state(n) {
- FieldState::Radio { selected: _, options } => if options.contains(&choice) {
- let field = self.doc.objects.get_mut(&self.form_ids[n]).unwrap().as_dict_mut().unwrap();
- field.set("V",Object::Name(choice.into_bytes()));
- Ok(())
- } else {
- Err(ValueError::InvalidSelection)
- },
- _ => Err(ValueError::TypeMismatch)
-
+ FieldState::Radio {
+ selected: _,
+ options,
+ } => {
+ if options.contains(&choice) {
+ let field = self
+ .doc
+ .objects
+ .get_mut(&self.form_ids[n])
+ .unwrap()
+ .as_dict_mut()
+ .unwrap();
+ field.set("V", Object::Name(choice.into_bytes()));
+ Ok(())
+ } else {
+ Err(ValueError::InvalidSelection)
+ }
+ }
+ _ => Err(ValueError::TypeMismatch),
}
}
- /// If the field at index `n` is a listbox or comboox field, selects the options in `choice`
- /// If it is not a listbox or combobox field or one of the choices is not a valid option, or if too many choices are selected, returns ValueError
+ /// If the field at index `n` is a listbox field, selects the options in `choice`
+ /// If it is not a listbox field or one of the choices is not a valid option, or if too many choices are selected, returns ValueError
///
/// # Panics
/// Will panic if n is larger than the number of fields
- pub fn set_choice(&mut self, n: usize, choices: Vec<String>) -> Result<(),ValueError> {
+ pub fn set_list_box(&mut self, n: usize, choices: Vec<String>) -> Result<(), ValueError> {
match self.get_state(n) {
- FieldState::ListBox { selected: _, options, multiselect } | FieldState::ComboBox { selected: _, options, multiselect } => if choices.iter().fold(true, |a,h| options.contains(h) && a) {
- if !multiselect && choices.len() > 1 {
- Err(ValueError::TooManySelected)
+ FieldState::ListBox {
+ selected: _,
+ options,
+ multiselect,
+ } => {
+ if choices.iter().fold(true, |a, h| options.contains(h) && a) {
+ if !multiselect && choices.len() > 1 {
+ Err(ValueError::TooManySelected)
+ } else {
+ let field = self
+ .doc
+ .objects
+ .get_mut(&self.form_ids[n])
+ .unwrap()
+ .as_dict_mut()
+ .unwrap();
+ match choices.len() {
+ 0 => field.set("V", Object::Null),
+ 1 => field.set(
+ "V",
+ Object::String(
+ choices[0].clone().into_bytes(),
+ StringFormat::Literal,
+ ),
+ ),
+ _ => field.set(
+ "V",
+ Object::Array(
+ choices
+ .iter()
+ .map(|x| {
+ Object::String(
+ x.clone().into_bytes(),
+ StringFormat::Literal,
+ )
+ })
+ .collect(),
+ ),
+ ),
+ };
+ Ok(())
+ }
} else {
- let field = self.doc.objects.get_mut(&self.form_ids[n]).unwrap().as_dict_mut().unwrap();
- match choices.len() {
- 0 => field.set("V", Object::Null),
- 1 => field.set("V", Object::String(choices[0].clone().into_bytes(),
- StringFormat::Literal)),
- _ => field.set("V", Object::Array(choices.iter().map(|x| Object::String(x.clone().into_bytes(),StringFormat::Literal)).collect()))
-
- };
- Ok(())
+ Err(ValueError::InvalidSelection)
}
-
- } else {
- Err(ValueError::InvalidSelection)
- },
- _ => Err(ValueError::TypeMismatch)
-
+ }
+ _ => Err(ValueError::TypeMismatch),
}
}
+ /// If the field at index `n` is a combobox field, selects the options in `choice`
+ /// If it is not a combobox field or one of the choices is not a valid option, or if too many choices are selected, returns ValueError
+ ///
+ /// # Panics
+ /// Will panic if n is larger than the number of fields
+ pub fn set_combo_box(&mut self, n: usize, choice: String) -> Result<(), ValueError> {
+ match self.get_state(n) {
+ FieldState::ComboBox {
+ selected: _,
+ options,
+ editable,
+ } => {
+ if options.contains(&choice) || editable {
+ let field = self
+ .doc
+ .objects
+ .get_mut(&self.form_ids[n])
+ .unwrap()
+ .as_dict_mut()
+ .unwrap();
+ field.set(
+ "V",
+ Object::String(choice.clone().into_bytes(), StringFormat::Literal),
+ );
+ Ok(())
+ } else {
+ Err(ValueError::InvalidSelection)
+ }
+ }
+ _ => Err(ValueError::TypeMismatch),
+ }
+ }
/// Saves the form to the specified path
- pub fn save<P: AsRef<Path>>(&mut self, path: P) -> Result<(),io::Error> {
+ pub fn save<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
self.doc.save(path).map(|_| ())
}
+
+ /// Saves the form to the specified path
+ pub fn save_to<W: Write>(&mut self, target: &mut W) -> Result<(), io::Error> {
+ self.doc.save_to(target)
+ }
}