From 1f481ae3c17dcc34d709023e0f3e14ed8b6f8925 Mon Sep 17 00:00:00 2001 From: Tyler K Date: Mon, 30 Sep 2024 09:30:00 -0700 Subject: [PATCH] Expanding explanation and example --- src/demo_gen/custom_functions.md | 87 ++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/src/demo_gen/custom_functions.md b/src/demo_gen/custom_functions.md index ae40daf..c1d43ba 100644 --- a/src/demo_gen/custom_functions.md +++ b/src/demo_gen/custom_functions.md @@ -1,45 +1,78 @@ # Making Custom Functions -Let's say you want to add your own custom demonstration functions for a given struct, without demo_gen automagically creating the content of JS functions for you. +## What is a custom function? -This is done with the `#[diplomat::demo(custom_func="filename.mjs")]` attribute, which can be added above any `struct` definition. demo_gen will search for files relative to `lib.rs`, and add the contents of `filename.mjs` to its output. +demo_gen tends towards automagical configuration. demo_gen will do its best to take Rust functions and convert them into JS output. -Then demo_gen will import the default export of `filename.mjs`, and append it to the list of [RenderInfo](https://github.com/rust-diplomat/diplomat/blob/main/docs/demo_gen.md#step-two-constructing-renderinfo) termini. +But there arise situations where we want to create our own custom Javascript functions to demonstrate our library's capabilities to the user, then add them to demo_gen's output. This may be the case if you want to demonstrate functionality that is more involved than demo_gen's automagical work. -Here's an example of what that looks like... +### Example +Let's look at the [quickstart](quickstart.md) repository for an example. -In rust: +We only have one function exposed: `get_add_str(left : u32, right: u32)`. -```rs -#[diplomat::bridge] -mod ffi { - #[diplomat::demo(custom_func="classname_demo.mjs")] - struct ClassName; -} +What if we have variables `a`, `b`, and `c`, and we want to show the user the results of calling: +`get_add_str(a, b)` and `get_add_str(b, c)`? -``` +We can do this without adding a new binding, through the use of a custom Javascript function. -Then in `classname_demo.mjs`, we write: +## \#\[diplomat::demo(custom_func="...")\] + +`#[diplomat::demo(custom_func="filename.mjs")]` can be added above any `struct` definition. demo_gen will search for files relative to `lib.rs`, and add the contents of `filename.mjs` to its output. + +Then demo_gen will import the default export of `filename.mjs`, and append it to the list of [RenderInfo](https://github.com/rust-diplomat/diplomat/blob/main/docs/demo_gen.md#step-two-constructing-renderinfo) termini. + +### Example +So, first we create a file called `adder_custom.mjs` in the same folder as `adder_bindings/src/lib.rs`: ```js +// adder_bindings/src/adder_custom.mjs +import { lib } from "./index.mjs"; export default { - "ClassName.SampleFunctionName": { - func: () => { alert("Hello world!"); }, - funcName: "ClassName.SampleFunctionName", - parameters: [ - - ] - }, - "ClassName.OtherFunctionName": { - func: (a) => { prompt(`Testing!${a}`); }, - funcName: "ClassName.OtherFunctionName", + "AddThreeVariables": { + func: (a, b, c) => { return lib.AddResult.getAddStr(a, b) + " and " + lib.AddResult.getAddStr(b, c); }, + funcName: "Add a + b, b + c", parameters: [ - name: "Prompt Question", - type: "string" + { + name: "a", + type: "number" + }, + { + name: "b", + type: "number" + }, + { + name: "c", + type: "number" + } ] } -}; +} +``` + +Then we make sure to link `adder_custom.mjs` in `lib.rs`: + +```rs +// adder_bindings/src/lib.rs +#[diplomat::bridge] +mod ffi { + use std::fmt::Write; + + #[diplomat::opaque] + #[diplomat::rust_link(basic_adder, Mod)] + #[diplomat::demo(custom_func="adder_custom.mjs")] + pub struct AddResult; + + impl AddResult { + pub fn get_add_str(left : u32, right : u32, write: &mut DiplomatWrite) { + write.write_str(&format!("{}", basic_adder::add(left, right))).unwrap(); + write.flush(); + } + } +} ``` -And our exported object is then added to `RenderInfo`s list of render termini, and is evaluated by the renderer accordingly! \ No newline at end of file +And our exported object is then added to `RenderInfo`s list of render termini, and is evaluated by the renderer accordingly! + +If you [regenerate the bindings and start the web server](https://rust-diplomat.github.io/book/demo_gen/quickstart.html#getting-started), you should see `Add a + b, b + c` in the list of functions. \ No newline at end of file