docs.sheetjs.com/docz/docs/03-demos/12-engines/21_boa.md

158 lines
3.7 KiB
Markdown
Raw Normal View History

2023-05-22 08:06:09 +00:00
---
title: Rust + Boa
pagination_prev: demos/bigdata/index
pagination_next: solutions/input
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::warning
In a production application, it is strongly recommended to use a binding for a
more performant engine like [`v8`](/docs/demos/engines/v8#rust)
:::
Boa is a pure-Rust JavaScript engine.
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
parsed and evaluated in a Boa context.
## Integration Details
_Initialize Engine_
A JS context can be constructed in one line:
```rust
use boa_engine::Context;
/* initialize */
let context = &mut Context::default();
```
The following helper function evaluates strings as JS code:
```rust
use std::string::String;
use boa_engine::{Context, Source, JsError};
/* simple wrapper to evaluate code snippets */
fn eval_code(c: &mut Context, code: &str) -> Result<String, JsError> {
let src = Source::from_bytes(code);
2023-06-05 20:12:53 +00:00
match c.eval(src) {
2023-05-22 08:06:09 +00:00
Ok(res) => { return Ok(res.to_string(c).unwrap().to_std_string_escaped()); }
Err(e) => { return Err(e); }
};
}
```
_Load SheetJS Scripts_
Boa provides a special helper to read source code from a path:
```rust
use std::path::Path;
use std::string::String;
use boa_engine::{Context, Source, JsError};
/* simple wrapper to evaluate an entire script file */
fn eval_file(c: &mut Context, path: &str) -> Result<String, JsError> {
let src = Source::from_filepath(Path::new(path)).unwrap();
2023-06-05 20:12:53 +00:00
match c.eval(src) {
2023-05-22 08:06:09 +00:00
Ok(res) => { return Ok(res.to_string(c).unwrap().to_std_string_escaped()); }
Err(e) => { return Err(e); }
};
}
// ...
/* load library */
match eval_file(context, "./xlsx.full.min.js") {
Ok(_res) => {}
Err(e) => { return eprintln!("Uncaught {e}"); }
}
```
To confirm the library is loaded, `XLSX.version` can be inspected:
```rust
/* get version string */
match eval_code(context, "XLSX.version") {
Ok(res) => { println!( "SheetJS library version {}", res); }
Err(e) => { return eprintln!("Uncaught {e}"); }
}
```
### Reading Files
Boa supports `ArrayBuffer` natively. This snippet reads data from a file into
`Vec<u8>` and stores the data as an `ArrayBuffer` in global scope:
```rust
/* read file */
let data: Vec<u8> = fs::read("pres.xlsx").unwrap();
let array: JsArrayBuffer = JsArrayBuffer::from_byte_block(data, context).unwrap();
let attrs = Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE;
context.register_global_property("buf", array, attrs);
/* parse with SheetJS */
match eval_code(context, "void (globalThis.wb = XLSX.read(buf))") {
Ok(_res) => { }
Err(e) => { return eprintln!("Uncaught {e}"); }
}
```
`wb` will be a variable in the JS environment that can be inspected using the
various SheetJS API functions.
## Complete Example
:::note
2023-06-05 20:12:53 +00:00
This demo was tested in the following deployments:
| Architecture | Date |
|:-------------|:-----------|
2023-07-06 07:21:41 +00:00
| `darwin-x64` | 2023-07-05 |
| `darwin-arm` | 2023-07-05 |
| `linux-x64` | 2023-07-05 |
2023-05-22 08:06:09 +00:00
:::
1) Create a new project:
```bash
2023-07-06 07:21:41 +00:00
cargo new sheetjs-boa
cd sheetjs-boa
2023-05-22 08:06:09 +00:00
cargo run
```
2) Add the `boa` crate from the Git repository:
```bash
cargo add --git https://github.com/boa-dev/boa boa_engine
```
3) Download the [Standalone build](/docs/getting-started/installation/standalone):
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
4) Download [`main.rs`](pathname:///boa/main.rs) and replace `src/main.rs`:
```bash
curl -L -o src/main.rs https://docs.sheetjs.com/boa/main.rs
```
5) Download [the test file](https://sheetjs.com/pres.xlsx) and run:
```bash
curl -LO https://sheetjs.com/pres.xlsx
cargo run
```
After a short wait, the contents will be displayed in CSV form.