| 
									
										
										
										
											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'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 22:09:08 +00:00
										 |  |  | :::warning 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The ["Complete Example"](#integration-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; | 
					
						
							|  |  |  | 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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | Architecture | Date       | | 
					
						
							|  |  |  | |:-------------|:-----------| | 
					
						
							| 
									
										
										
										
											2023-11-04 05:05:26 +00:00
										 |  |  | | `darwin-x64` | 2023-11-03 | | 
					
						
							| 
									
										
										
										
											2023-10-21 11:15:28 +00:00
										 |  |  | | `darwin-arm` | 2023-10-20 | | 
					
						
							| 
									
										
										
										
											2023-10-29 03:22:50 +00:00
										 |  |  | | `win10-x64`  | 2023-10-28 | | 
					
						
							| 
									
										
										
										
											2023-12-02 08:39:35 +00:00
										 |  |  | | `win11-arm`  | 2023-12-01 | | 
					
						
							| 
									
										
										
										
											2024-01-03 06:47:00 +00:00
										 |  |  | | `linux-x64`  | 2023-12-07 | | 
					
						
							| 
									
										
										
										
											2023-12-02 08:39:35 +00:00
										 |  |  | | `linux-arm`  | 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
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-22 06:32:55 +00:00
										 |  |  | 3) Download the SheetJS Standalone script and move to the project directory: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <ul> | 
					
						
							|  |  |  | <li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li> | 
					
						
							|  |  |  | </ul> | 
					
						
							| 
									
										
										
										
											2023-05-22 08:06:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | <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 | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ::: |