forked from sheetjs/docs.sheetjs.com
		
	rusty-sheetjs
This commit is contained in:
		
							parent
							
								
									173ba31e0a
								
							
						
					
					
						commit
						58f45f9574
					
				@ -260,3 +260,72 @@ g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
 | 
			
		||||
 | 
			
		||||
If the program succeeded, the CSV contents will be printed to console and the
 | 
			
		||||
file `sheetjsw.xlsb` will be created.  That file can be opened with Excel.
 | 
			
		||||
 | 
			
		||||
## Bindings
 | 
			
		||||
 | 
			
		||||
V8 is easily embeddable.  Bindings exist for many languages.
 | 
			
		||||
 | 
			
		||||
### Rust
 | 
			
		||||
 | 
			
		||||
The `v8` crate provides binary builds and straightforward bindings. The Rust
 | 
			
		||||
code is similar to the C++ code.
 | 
			
		||||
 | 
			
		||||
Pulling data from an `ArrayBuffer` back into Rust involves an unsafe operation:
 | 
			
		||||
 | 
			
		||||
```rust
 | 
			
		||||
/* assuming JS code returns an ArrayBuffer, copy result to a Vec<u8> */
 | 
			
		||||
fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
 | 
			
		||||
  let source = v8::String::new(scope, &code).unwrap();
 | 
			
		||||
  let script = v8::Script::compile(scope, source, None).unwrap();
 | 
			
		||||
  let result: v8::Local<v8::ArrayBuffer> = script.run(scope).unwrap().try_into().unwrap();
 | 
			
		||||
  /* In C++, `Data` returns a pointer. Collecting data into Vec<u8> is unsafe */
 | 
			
		||||
  unsafe { return std::slice::from_raw_parts_mut(
 | 
			
		||||
    result.data().unwrap().cast::<u8>().as_ptr(),
 | 
			
		||||
    result.byte_length()
 | 
			
		||||
  ).to_vec(); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 May 22 against `v8` crate version `0.71.2`
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Create a new project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cargo new sheetjs-rustyv8
 | 
			
		||||
cd sheetjs-rustyv8
 | 
			
		||||
cargo run
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Add the `v8` crate:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cargo add v8
 | 
			
		||||
cargo run
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
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:///v8/main.rs) and replace `src/main.rs`:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
5) Download [the test file](https://sheetjs.com/pres.numbers) and run:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -LO https://sheetjs.com/pres.numbers
 | 
			
		||||
cargo run pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If the program succeeded, the CSV contents will be printed to console and the
 | 
			
		||||
file `sheetjsw.xlsb` will be created.  That file can be opened with Excel.
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ engine.put("bytes", Files.readAllBytes(Paths.get(args[0])));
 | 
			
		||||
engine.eval(
 | 
			
		||||
  "function b2a(b) {" +
 | 
			
		||||
    "var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" +
 | 
			
		||||
    "for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" +
 | 
			
		||||
    "for(var i = 0; i < out.length; i++) out[i] = b[i] & 0xFF;" +
 | 
			
		||||
    "return out;" +
 | 
			
		||||
  "}" +
 | 
			
		||||
  "var u8a = b2a(bytes)"
 | 
			
		||||
@ -92,10 +92,16 @@ engine.eval("var wb = XLSX.read(u8a, {type: 'array'})");
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 March 27 using:
 | 
			
		||||
This demo was tested in the following deployments:
 | 
			
		||||
 | 
			
		||||
- OpenJDK 19.0.1  + Nashorn 15.4 standalone
 | 
			
		||||
- OpenJDK 11.0.18 + Official Nashorn
 | 
			
		||||
| OpenJDK | Nashorn         | Date       |
 | 
			
		||||
|:--------|:----------------|:-----------|
 | 
			
		||||
| 20.0.1  | 15.4 standalone | 2023-05-21 |
 | 
			
		||||
| 19.0.2  | 15.4 standalone | 2023-05-21 |
 | 
			
		||||
| 17.0.6  | 15.4 standalone | 2023-05-21 |
 | 
			
		||||
| 15.0.10 | 15.4 standalone | 2023-05-21 |
 | 
			
		||||
| 11.0.19 | Built-in        | 2023-05-21 |
 | 
			
		||||
| 1.8.0   | Built-in        | 2023-05-21 |
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										151
									
								
								docz/docs/03-demos/12-engines/21_boa.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										151
									
								
								docz/docs/03-demos/12-engines/21_boa.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
			
		||||
---
 | 
			
		||||
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);
 | 
			
		||||
  match c.eval_script(src) {
 | 
			
		||||
    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();
 | 
			
		||||
  match c.eval_script(src) {
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
This demo was tested on 2023 May 22
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Create a new project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
cargo new sheetjs-rs
 | 
			
		||||
cd sheetjs-rs
 | 
			
		||||
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.
 | 
			
		||||
@ -10,7 +10,7 @@ import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
:::warning
 | 
			
		||||
 | 
			
		||||
In a production application, it is strongly recommended to use a binding for a
 | 
			
		||||
C engine like [`JavaScript::Duktape`](/docs/demos/engines/duktape)
 | 
			
		||||
C engine like [`JavaScript::Duktape`](/docs/demos/engines/duktape#perl)
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -52,11 +52,36 @@ other exports.  APIs that accept pointers without length should be avoided.
 | 
			
		||||
Base64 strings are safe for passing between JS and native code, but they should
 | 
			
		||||
only be used when there is no safe way to pass `ArrayBuffer` or `Uint8Array`.
 | 
			
		||||
 | 
			
		||||
**Byte Conventions**
 | 
			
		||||
 | 
			
		||||
Java has no native concept of unsigned bytes. Values in a `byte[]` are clamped
 | 
			
		||||
to the range `-128 .. 127`. They need to be fixed within the JS engine.
 | 
			
		||||
 | 
			
		||||
Some engines support typed arrays. The `Uint8Array` constructor will fix values:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var signed_data = [-48, -49, 17, -32, /* ... */]; // 0xD0 0xCF 0x11 0xE0 ...
 | 
			
		||||
var fixed_data = new Uint8Array(signed_data);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
When `Uint8Array` is not supported, values can be fixed with bitwise operations:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var signed_data = [-48, -49, 17, -32, /* ... */]; // 0xD0 0xCF 0x11 0xE0 ...
 | 
			
		||||
var fixed_data = new Array(signed_data.length);
 | 
			
		||||
for(var i = 0; i < signed_data.length; ++i) fixed_data[i] = signed_data[i] & 0xFF;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Engines
 | 
			
		||||
 | 
			
		||||
This list is sorted in alphabetical order.
 | 
			
		||||
 | 
			
		||||
### Boa
 | 
			
		||||
 | 
			
		||||
Boa is an embeddable JS engine written in Rust.
 | 
			
		||||
 | 
			
		||||
This demo has been moved [to a dedicated page](/docs/demos/engines/boa).
 | 
			
		||||
 | 
			
		||||
### ChakraCore
 | 
			
		||||
 | 
			
		||||
ChakraCore is an embeddable JS engine written in C++.
 | 
			
		||||
@ -267,3 +292,12 @@ This demo has been moved [to a dedicated page](/docs/demos/engines/quickjs).
 | 
			
		||||
Rhino is an ES3+ engine in Java.
 | 
			
		||||
 | 
			
		||||
This demo has been moved [to a dedicated page](/docs/demos/engines/rhino).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### V8
 | 
			
		||||
 | 
			
		||||
V8 is an embeddable JS engine written in C++. It powers Chromium and Chrome,
 | 
			
		||||
NodeJS and Deno, Adobe UXP and other platforms.
 | 
			
		||||
 | 
			
		||||
This demo has been moved [to a dedicated page](/docs/demos/engines/v8).
 | 
			
		||||
The demo includes examples in C++ and Rust.
 | 
			
		||||
 | 
			
		||||
@ -142,7 +142,7 @@ const config = {
 | 
			
		||||
      prism: {
 | 
			
		||||
        theme: lightCodeTheme,
 | 
			
		||||
        darkTheme: darkCodeTheme,
 | 
			
		||||
        additionalLanguages: [ "swift", "java", "csharp", "perl", "ruby", "cpp", "applescript", "liquid" ],
 | 
			
		||||
        additionalLanguages: [ "swift", "java", "csharp", "perl", "ruby", "cpp", "applescript", "liquid", "rust" ],
 | 
			
		||||
      },
 | 
			
		||||
      liveCodeBlock: {
 | 
			
		||||
        playgroundPosition: 'top'
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										58
									
								
								docz/static/boa/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										58
									
								
								docz/static/boa/main.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
/*! sheetjs (C) SheetJS -- https://sheetjs.com */
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::string::String;
 | 
			
		||||
use std::fs;
 | 
			
		||||
 | 
			
		||||
use boa_engine::{Context, Source, JsError};
 | 
			
		||||
use boa_engine::object::builtins::JsArrayBuffer;
 | 
			
		||||
use boa_engine::property::Attribute;
 | 
			
		||||
 | 
			
		||||
fn eval_file(c: &mut Context, path: &str) -> Result<String, JsError> {
 | 
			
		||||
  let src = Source::from_filepath(Path::new(path)).unwrap();
 | 
			
		||||
  match c.eval_script(src) {
 | 
			
		||||
    Ok(res) => { return Ok(res.to_string(c).unwrap().to_std_string_escaped()); }
 | 
			
		||||
    Err(e) => { return Err(e); }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn eval_code(c: &mut Context, code: &str) -> Result<String, JsError> {
 | 
			
		||||
  let src = Source::from_bytes(code);
 | 
			
		||||
  match c.eval_script(src) {
 | 
			
		||||
    Ok(res) => { return Ok(res.to_string(c).unwrap().to_std_string_escaped()); }
 | 
			
		||||
    Err(e) => { return Err(e); }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
  let context = &mut Context::default();
 | 
			
		||||
 | 
			
		||||
  /* load library */
 | 
			
		||||
  match eval_file(context, "./xlsx.full.min.js") {
 | 
			
		||||
    Ok(_res) => {}
 | 
			
		||||
    Err(e) => { return eprintln!("Uncaught {e}"); }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* get version string */
 | 
			
		||||
  match eval_code(context, "XLSX.version") {
 | 
			
		||||
    Ok(res) => { println!( "SheetJS library version {}", res); }
 | 
			
		||||
    Err(e) => { return eprintln!("Uncaught {e}"); }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* 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 workbook and assign to global `wb` property */
 | 
			
		||||
  match eval_code(context, "void (globalThis.wb = XLSX.read(buf))") {
 | 
			
		||||
    Ok(_res) => { }
 | 
			
		||||
    Err(e) => { return eprintln!("Uncaught {e}"); }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* print CSV of first worksheet */
 | 
			
		||||
  match eval_code(context, "XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]])") {
 | 
			
		||||
    Ok(res) => { println!( "{}", res); }
 | 
			
		||||
    Err(e) => { return eprintln!("Uncaught {e}"); }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -21,7 +21,7 @@ public class SheetJSNashorn {
 | 
			
		||||
    /* convert signed byte array to JS Uint8Array or unsigned byte array */
 | 
			
		||||
    engine.eval("function b2a(b) {" +
 | 
			
		||||
      "var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" +
 | 
			
		||||
      "for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;" +
 | 
			
		||||
      "for(var i = 0; i < out.length; i++) out[i] = b[i] & 0xFF;" +
 | 
			
		||||
      "return out;" +
 | 
			
		||||
    "}" +
 | 
			
		||||
    "var u8a = b2a(bytes)");
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								docz/static/v8/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										69
									
								
								docz/static/v8/main.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
/*! sheetjs (C) SheetJS -- https://sheetjs.com */
 | 
			
		||||
/* run code, get result as a Rust String */
 | 
			
		||||
fn eval_code(scope: &mut v8::HandleScope, code: &str) -> std::string::String {
 | 
			
		||||
  let source = v8::String::new(scope, &code).unwrap();
 | 
			
		||||
  let script = v8::Script::compile(scope, source, None).unwrap();
 | 
			
		||||
  let result = script.run(scope).unwrap();
 | 
			
		||||
  return result.to_string(scope).unwrap().to_rust_string_lossy(scope);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* assuming JS code returns an ArrayBuffer, copy result to a Vec<u8> */
 | 
			
		||||
fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
 | 
			
		||||
  let source = v8::String::new(scope, &code).unwrap();
 | 
			
		||||
  let script = v8::Script::compile(scope, source, None).unwrap();
 | 
			
		||||
  let result: v8::Local<v8::ArrayBuffer> = script.run(scope).unwrap().try_into().unwrap();
 | 
			
		||||
  unsafe { return std::slice::from_raw_parts_mut(result.data().unwrap().cast::<u8>().as_ptr(), result.byte_length()).to_vec(); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
  /* initialize */
 | 
			
		||||
  let platform = v8::new_default_platform(0, false).make_shared();
 | 
			
		||||
  v8::V8::initialize_platform(platform);
 | 
			
		||||
  v8::V8::initialize();
 | 
			
		||||
 | 
			
		||||
  let isolate = &mut v8::Isolate::new(Default::default());
 | 
			
		||||
  let handle_scope = &mut v8::HandleScope::new(isolate);
 | 
			
		||||
  let context = v8::Context::new(handle_scope);
 | 
			
		||||
  let context_scope = &mut v8::ContextScope::new(handle_scope, context);
 | 
			
		||||
 | 
			
		||||
  /* load library */
 | 
			
		||||
  {
 | 
			
		||||
    let script = std::fs::read_to_string("./xlsx.full.min.js").expect("Error reading xlsx.full.min.js");
 | 
			
		||||
    let _result = eval_code(context_scope, &script);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* get version string */
 | 
			
		||||
  {
 | 
			
		||||
    let result = eval_code(context_scope, "XLSX.version");
 | 
			
		||||
    println!("SheetJS library version {}", result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* read file */
 | 
			
		||||
  {
 | 
			
		||||
    let path: String = std::env::args().collect::<Vec<_>>().into_iter().nth(1).unwrap().to_string();
 | 
			
		||||
    let data: Vec<u8> = std::fs::read(path.clone()).unwrap();
 | 
			
		||||
    let back: v8::UniqueRef<v8::BackingStore> = v8::ArrayBuffer::new_backing_store_from_vec(data);
 | 
			
		||||
    let shared = back.make_shared();
 | 
			
		||||
    let ab: v8::Local<v8::ArrayBuffer> = v8::ArrayBuffer::with_backing_store(context_scope, &shared);
 | 
			
		||||
    let key = v8::String::new(context_scope, "buf").unwrap();
 | 
			
		||||
    context.global(context_scope).set(context_scope, key.into(), ab.into());
 | 
			
		||||
    println!("Loaded file {}", path);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* parse workbook and assign to global `wb` property */
 | 
			
		||||
  {
 | 
			
		||||
    let _result = eval_code(context_scope, "void (globalThis.wb = XLSX.read(buf))");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* print CSV of first worksheet */
 | 
			
		||||
  {
 | 
			
		||||
    let result = eval_code(context_scope, "XLSX.utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]])");
 | 
			
		||||
    println!("{}", result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* write sheetjsw.xlsb */
 | 
			
		||||
  {
 | 
			
		||||
    let result = eval_code_ab(context_scope, "XLSX.write(wb, {type:'array', bookType:'xlsb'})");
 | 
			
		||||
    std::fs::write("sheetjsw.xlsb", result).unwrap();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user