printpdf
printpdf copied to clipboard
using with wasm-pack shared reference problem
Hi! I am new to Rust. I want to show wasm generated pdf with live changes in browser.
How can I solve this shared reference problem? Is there a trait implementaion missing? How can I clone
or take ownership
of the doc? thank you.
Purpose:
to convert pdf to bytes array and sent to js side.
Code
use printpdf::*;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn create() -> JsValue {
let (doc, page1, layer1) =
PdfDocument::new("PDF_Document_title", Mm(247.0), Mm(210.0), "Layer 1");
let bytes: Vec<u8> = doc.save_to_bytes().unwrap();
serde_wasm_bindgen::to_value(&bytes).unwrap()
}
Build Command
wasm-pack build --target bundler
Error
[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
Compiling printpdf v0.5.3
error[E0507]: cannot move out of `m.modification_date` which is behind a shared reference
--> /home/ulvi/.cargo/registry/src/github.com-1ecc6299db9ec823/printpdf-0.5.3/src/document_info.rs:77:56
|
77 | let info_mod_date = to_pdf_time_stamp_metadata(m.modification_date);
| ^^^^^^^^^^^^^^^^^^^ move occurs because `m.modification_date` has type `js_sys_date::OffsetDateTime`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `m.creation_date` which is behind a shared reference
--> /home/ulvi/.cargo/registry/src/github.com-1ecc6299db9ec823/printpdf-0.5.3/src/document_info.rs:78:59
|
78 | let info_create_date = to_pdf_time_stamp_metadata(m.creation_date);
| ^^^^^^^^^^^^^^^ move occurs because `m.creation_date` has type `js_sys_date::OffsetDateTime`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `m.creation_date` which is behind a shared reference
--> /home/ulvi/.cargo/registry/src/github.com-1ecc6299db9ec823/printpdf-0.5.3/src/xmp_metadata.rs:49:43
|
49 | let create_date = to_pdf_xmp_date(m.creation_date);
| ^^^^^^^^^^^^^^^ move occurs because `m.creation_date` has type `js_sys_date::OffsetDateTime`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `m.modification_date` which is behind a shared reference
--> /home/ulvi/.cargo/registry/src/github.com-1ecc6299db9ec823/printpdf-0.5.3/src/xmp_metadata.rs:50:49
|
50 | let modification_date = to_pdf_xmp_date(m.modification_date);
| ^^^^^^^^^^^^^^^^^^^ move occurs because `m.modification_date` has type `js_sys_date::OffsetDateTime`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `m.metadata_date` which is behind a shared reference
--> /home/ulvi/.cargo/registry/src/github.com-1ecc6299db9ec823/printpdf-0.5.3/src/xmp_metadata.rs:51:45
|
51 | let metadata_date = to_pdf_xmp_date(m.metadata_date);
| ^^^^^^^^^^^^^^^ move occurs because `m.metadata_date` has type `js_sys_date::OffsetDateTime`, which does not implement the `Copy` trait
For more information about this error, try `rustc --explain E0507`.
error: could not compile `printpdf` due to 5 previous errors
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit status: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"
@ulvido you can't, it would need modifications to the user code in this example
Fixed with https://github.com/fschutt/printpdf/pull/127
Thank you. I can confirm that problem resolved. I have notations:
- But one should use printpdf from git repo not with
cargo add printpdf
because at the moment crates.io version is outdated. - Vec<u8> send with serde is somehow broken. You can create your own data type and use
serde_bytes
for the payload and send it to the javascript side.
EXAMPLE
#Cargo.toml
#...
[dependencies]
wasm-bindgen = "0.2.63"
serde = { version = "1.0.160", features = ["derive"] }
serde-wasm-bindgen = "0.5.0"
serde_bytes = "0.11.9"
printpdf = { git = "https://github.com/fschutt/printpdf.git" }
#lib.rs
use printpdf::*;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
mod utils;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet() {
alert("Hello, printpdf!");
}
#[derive(Deserialize, Serialize)]
struct Message {
#[serde(with = "serde_bytes")]
payload: Vec<u8>,
}
#[wasm_bindgen]
pub fn create(title: &str, text: &str) -> JsValue {
let (doc, page1, layer1) = PdfDocument::new(title, Mm(247.0), Mm(210.0), "Layer 1");
let current_layer = doc.get_page(page1).get_layer(layer1);
// use built-in font
let font = doc.add_builtin_font(BuiltinFont::TimesRoman).unwrap();
current_layer.begin_text_section();
current_layer.use_text(text, 22.0, Mm(30.0), Mm(30.0), &font);
current_layer.end_text_section();
let bytes: Vec<u8> = doc.save_to_bytes().unwrap();
let m = Message { payload: bytes };
serde_wasm_bindgen::to_value(&m).unwrap()
}
USAGE
#App.svelte
<script lang="ts">
let pdf_title;
let pdf_text;
import init, { greet, create } from "pdf-maker"; // my wasm create name
init().then((module) => {
console.log(module);
// greet();
});
const createpdf = () => {
const blob = new Blob([create(pdf_title, pdf_text).payload], {
type: "application/pdf",
});
const blobURL = URL.createObjectURL(blob);
window.open(blobURL);
};
</script>
<main>
<div class="card">
<input
bind:value={pdf_title}
placeholder="PDF Title"
type="text"
/>
</div>
<div class="card">
<textarea
bind:value={pdf_text}
placeholder="PDF Text"
cols="30"
rows="10"
/>
</div>
<div class="card">
<button on:click={createpdf }>Create PDF</button>
</div>
</main>