docs.sheetjs.com/docz/docs/03-demos/42-engines/21-boa.md

179 lines
4.5 KiB
Markdown
Raw Permalink 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';
:::danger pass
2023-05-22 08:06:09 +00:00
In a production application, it is strongly recommended to use a binding for a
more performant engine like [`v8`](/docs/demos/engines/v8#rust)
:::
2023-10-29 03:22:50 +00:00
[Boa](https://boajs.dev/) is a JavaScript engine written in Rust.
2023-05-22 08:06:09 +00:00
2023-10-29 03:22:50 +00:00
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
2024-04-12 01:04:37 +00:00
The ["Complete Example"](#complete-example) section creates a command-line tool
for reading data from spreadsheets and generating CSV rows.
2023-05-22 08:06:09 +00:00
## Integration Details
2023-10-29 03:22:50 +00:00
### Initialize Boa
2023-05-22 08:06:09 +00:00
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); }
};
}
```
2023-10-29 03:22:50 +00:00
### Load SheetJS Scripts
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be parsed and evaluated in a Boa context.
2023-05-22 08:06:09 +00:00
Boa provides a special helper to read source code from a path:
```rust
use std::path::Path;
use std::string::String;
2024-03-16 16:04:18 +00:00
use boa_engine::{js_string, Context, Source, JsError};
2023-05-22 08:06:09 +00:00
/* 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;
2024-03-16 16:04:18 +00:00
context.register_global_property(js_string!("buf"), array, attrs);
2023-05-22 08:06:09 +00:00
/* 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
2023-11-13 11:17:25 +00:00
:::note Tested Deployments
2023-05-22 08:06:09 +00:00
2023-06-05 20:12:53 +00:00
This demo was tested in the following deployments:
2024-03-16 16:04:18 +00:00
| Architecture | Boa | Date |
|:-------------|:---------|:-----------|
2024-04-26 04:16:13 +00:00
| `darwin-x64` | `0.18.0` | 2024-04-25 |
2024-03-16 16:04:18 +00:00
| `darwin-arm` | `0.17.3` | 2023-10-20 |
2024-04-26 04:16:13 +00:00
| `win10-x64` | `0.18.0` | 2024-04-25 |
2024-03-16 16:04:18 +00:00
| `win11-arm` | `0.17.3` | 2023-12-01 |
2024-03-22 04:45:40 +00:00
| `linux-x64` | `0.18.0` | 2024-03-21 |
2024-03-16 16:04:18 +00:00
| `linux-arm` | `0.17.3` | 2023-12-01 |
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
```
2023-07-21 09:17:32 +00:00
2) Add the `boa_engine` crate:
2023-05-22 08:06:09 +00:00
```bash
2023-07-21 09:17:32 +00:00
cargo add boa_engine
2023-05-22 08:06:09 +00:00
```
2024-04-26 04:16:13 +00:00
3) Download the SheetJS Standalone script and test file. Save both files in the
project directory:
2023-09-22 06:32:55 +00:00
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
2024-04-26 04:16:13 +00:00
<li><a href="https://docs.sheetjs.com/pres.xlsx">pres.xlsx</a></li>
2023-09-22 06:32:55 +00:00
</ul>
2023-05-22 08:06:09 +00:00
<CodeBlock language="bash">{`\
2024-04-26 04:16:13 +00:00
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.xlsx`}
2023-05-22 08:06:09 +00:00
</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
```
2024-04-26 04:16:13 +00:00
5) Build and run the app in release mode:
2023-05-22 08:06:09 +00:00
```bash
2023-08-31 22:09:08 +00:00
cargo run --release
2023-05-22 08:06:09 +00:00
```
After a short wait, the contents will be displayed in CSV form.
2023-08-31 22:09:08 +00:00
:::caution pass
The default debug build is not optimized and can elicit stack overflow errors.
It is strongly encouraged to use `--release` when possible.
:::