Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New FFI Macro #132

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

New FFI Macro #132

wants to merge 1 commit into from

Conversation

actioninja
Copy link
Member

@actioninja actioninja commented May 14, 2023

Brand new ludicrously overengineered macro for automagically™ interoping with byond smoothly and cleanly.

Here's what you can do with the new macro

All of these are callable directly from byond.

Write bare functions without being wrapped in a macro

#[byond_fn]
pub fn example_byond_fn() {
    let x = "yeah, we can bind vars";
    println!("{x}");
}

Have string arguments and return strings

#[byond_fn]
pub fn concat(first: &str, second: &str) -> String {
    format!("{first}{second")
}

Have arbitrary args that can be parsed from strings and return arbitrary types that can be converted to strings

#[byond_fn]
pub fn add(arg1: u8, arg2: u8) -> u8 {
    arg1 + arg2
}

Have some arguments be optional and not required to be passed

#[byond_fn]
pub fn example_optional_params(arg1: u8, arg2: Option<u8>) -> u8 {
    arg1 + arg2.unwrap_or(0)
}

Gracefully handle errors

#[byond_fn]
pub fn do_something_falliable(dunno: &str) -> Result<String, WhateverError> {
    let cool = probably_something_cool(dunno)?;
    let oh_no = actually_it_was_lame(cool)?;
    Ok(oh_no)
}

Automagic JSON Transport

pub fn fungle_the_goobler(goobler: Json<Goobler>) -> Json<Fungled> {
    let fungled = goobler.into_inner().fungle();
    Json(fungled)
}

New macro lives here (at the moment): https://github.com/actioninja/byond_fn

Docs here: https://docs.rs/byond_fn/0.5.1/byond_fn/

How the hell does this work?

In a very overcomplicated way

The tl;dr is it uses a trait to parse arguments from strings, and a separate trait to serialize back to string. There's blanket impls over Option and Result as well for optional args and error handling respectively.

This will be better documented later, read the code, the docs, etc

Error handling

This is very much in flux right now. Especially considering that the best way to handle this may change when FFI V2 becomes available. How it currently works can be found in the docs (though these docs may not be accurate atm): https://docs.rs/byond_fn/0.5.1/byond_fn/str_ffi/index.html#errors

Goals

I never really was super happy with the existing macro. Since it puts the function body inside a macro call, you lose a lot of IDE niceness since inside macros could be anything. On top of that, it always was kind of weird to me that each function was expected to just do the boilerplate of parsing each string argument manually when this is going to be the same in the overwhelming amount of usecases.

The unclear and not well documented nature of the previous macro resulted in a lot of cargo cult as well. Lots of functions that return results despite having no fallibility.

Someone mentioned in coderbus a while ago that it would be nice if the actual FFI junk could be pulled out of rust-g so it could be reused elsewhere more easily. Since proc macros require their own crate anyways, this makes a good opportunity to do so.

byond_fn todo

  • Finalize the argument structure and how FFI types should be specified
  • Finalize the error handling structure
  • Implement some way of automatically generating the byond-side call signature (companion crate for usage in build.rs?)
  • Fully cover all pub api with documentation
  • Write some basic unit tests
  • Implement the new byond FFI interface

Things that should happen before this is merged

  • finalize byond_fn structure and output and hit 1.0 (above todo list should be finished)
  • convert all existing functions in rust-g to use the new macro
  • bring byond_fn under the tgstation org and give more accounts crates.io publish perms
  • run a built binary using the new macro in prod for a while to check against regressions

@AffectedArc07
Copy link
Member

fungle_the_goobler

@Cyprex
Copy link

Cyprex commented May 14, 2023

How (un)performant is this?

@actioninja
Copy link
Member Author

How (un)performant is this?

Shouldn't be meaningfully different from the existing macro. The two potential vectors for performance differences are the extra error handling and sanity checking (of which this mostly consists of a check to make sure the amount of arguments is correct), and the extra trait function calls which are all static dispatch anyways.

@actioninja
Copy link
Member Author

Going to put this on hold until ffiv2 comes out

@AffectedArc07
Copy link
Member

FFIV2 is out - Tiger is currently making a crate for it https://github.com/spacestation13/byondapi-rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants