aes_externalobj 0.1.2

ExtendScript external object library implementation in Rust
Documentation
# ExtendScript ExternalObject (aes_externalobj)

A Rust implementation of Adobe ExtendScript external object interface, allowing creation of native extensions for Adobe applications.

## Motivation
ExtendScript is based on JavaScript ES3, which is quite outdated. The old interface has a C/C++ based external object, which allowed you to create your own extensions. The goal of this project is to provide a Rust implementation of the ExtendScript external object interface, but with a more modern and safe Rust wrapper around the C ABI.

## Installation

Add these dependencies to your `Cargo.toml`:

```toml
[dependencies]
aes_externalobj = "0.1.0"
ctor = "0.2"  # Required for function signature registration
```

## Usage

To create an ExtendScript external object, you need to use the provided macros:

```rust
use aes_externalobj::{ext_ver, ext_init, ext_term, ext_export, JsScript, LiveObject};

// Version function
#[ext_ver]
fn version() -> i32 {
    1 // Library version
}

// Initialization function
#[ext_init]
fn init() {
    println!("Initializing library");
}

// Termination function
#[ext_term]
fn term() {
    // Cleanup code here
}

// Example function that returns a greeting string
#[ext_export]
fn HelloFromRust(name: String) -> String {
    format!("Hello from Rust, {}!", name)
}

// Example function with multiple arguments
#[ext_export]
fn HelloArgs(name: String, age: i32) -> String {
    format!("Hello from Rust, {} {}!", name, age)
}

// Example function that handles JavaScript code
#[ext_export]
fn EvalJS(code: JsScript) -> JsScript {
    // Process JavaScript code
    code
}

// Example function that works with LiveObjects
#[ext_export]
fn CreateObject(object: LiveObject) -> LiveObject {
    object
}
```

Then in ExtendScript you can use it like this:

```javascript
// Load the external object
var ext = new ExternalObject("lib:your_library_name");

// Call string function
var message = ext.HelloFromRust("World");
alert(message); // Shows "Hello from Rust, World!"

// Call function with multiple arguments
var greeting = ext.HelloArgs("John", 25);
alert(greeting); // Shows "Hello from Rust, John 25!"

// Work with JavaScript code
var result = ext.EvalJS("your_script_here");

// Clean up
ext.unload();
```




## Supported Types

The library supports the following types for function arguments and return values:

- `String` - ExtendScript strings (signature: "s")
- `i32` - Signed 32-bit integers (signature: "d")
- `u32` - Unsigned 32-bit integers (signature: "u")
- `f64` - 64-bit floating point numbers (signature: "f")
- `bool` - Boolean values (signature: "b")
- `JsScript` - JavaScript code (signature: "a")
- `LiveObject` - ExtendScript live objects (signature: "o")

Function signatures are automatically generated based on argument types. For example:
- `HelloFromRust_s` - function takes one string argument
- `HelloArgs_sd` - function takes string and integer arguments
- `EvalJS_a` - function takes any type argument (JavaScript code)
- `CreateObject_o` - function takes object argument


### Working with Server Interface

The library provides access to the ExtendScript server interface through `get_server_interface()`. This allows you to evaluate ExtendScript code and interact with the Adobe application:

```rust
use aes_externalobj::{get_server_interface, TaggedData};

#[ext_export]
fn eval_script(script: String) -> TaggedData {
    // Get server interface
    let server = match get_server_interface() {
        Some(server) => server,
        None => {
            println!("Server interface not found");
            return TaggedData::new_undefined();
        }
    };

    // Evaluate ExtendScript code
    match server.eval(&script) {
        Ok(result) => {
            println!("Script evaluation successful");
            result
        },
        Err(e) => {
            println!("Script evaluation failed: {}", e);
            TaggedData::new_undefined()
        }
    }
}
```

In ExtendScript, you can use it like this:

```javascript
var ext = new ExternalObject("lib:your_library_name");

// Evaluate ExtendScript code
var result = ext.eval_script("app.version");
// The result will contain the version of the Adobe application

ext.unload();
```


## Building

### Prerequisites

- Rust 1.56 or higher
- `ctor` crate for function signature registration

### Build Commands

```bash
cargo build --release
```

## Documentation

For detailed documentation, visit [docs.rs/aes_externalobj](https://docs.rs/aes_externalobj)

## Features

- [x] Basic implementation
- [x] Macro-based function exports
- [x] Automatic signature generation
- [x] JavaScript code handling
- [ ] Live objects support
- [ ] Extend SoServerInterface
- [ ] Add JavaScript objects
- [ ] Complete documentation
- [ ] Enhanced error handling

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under dual MIT/Apache-2.0 license. See [LICENSE-MIT](LICENSE-MIT) and [LICENSE-APACHE](LICENSE-APACHE) for details.