org-arl / fjage

Framework for Java and Groovy Agents
https://fjage.readthedocs.io/en/latest/
Other
25 stars 13 forks source link

A pure-Rust gateway for Fjåge with C API compatibility #316

Open brodiealexander opened 1 month ago

brodiealexander commented 1 month ago

A few weeks ago, I was reading about a framework for Rust serialization/deserialization framework called Serde, which has the ability to derive serialization/deserialization methods using a macro like so:

#[derive(Serialize, Deserialize)]
pub struct ParameterReq {
    pub msgID: String,
    pub perf: Performative,
    pub recipient: String,
    pub inReplyTo: Option<String>,
    pub sender: String,
    pub sentAt: i64,
    pub index: i64,
    pub param: Option<String>,
    pub value: Value,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub requests: Option<HashMap<String, Value>>,
}

I sat down to start playing with it, and now I have a (mostly) working Fjage gateway written in Rust.

While providing the ability to interface with Fjage from Rust programs is my eventual goal, so far, I have been focused on making this package binary-compatible with the C gateway API. As of right now, you can download the Rust gateway, build it, link the resulting library against the UnetSocket C API, and successfully send and receive a datagram. Further, it passes all of the C gateway's tests when linked with test_fjage.c

In addition to implementing the base C API, it also provides the following extensions:

#include "fjage.h"

// New to fjage-rs
// double param extension
int fjage_param_set_double(fjage_gw_t gw, fjage_aid_t aid, const char *param, double value, int ndx);
double fjage_param_get_double(fjage_gw_t gw, fjage_aid_t aid, const char *param, int ndx, double defval);

// array params extension
// setters
int fjage_param_set_int_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, int *value, int len, int ndx);
int fjage_param_set_long_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, long *value, int len, int ndx);
int fjage_param_set_float_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, float *value, int len, int ndx);
int fjage_param_set_double_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, double *value, int len, int ndx);
int fjage_param_set_string_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, const char **value, int len, int ndx);

// getters
int fjage_param_get_int_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, int *value, int maxlen, int ndx);
int fjage_param_get_long_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, long *value, int maxlen, int ndx);
int fjage_param_get_float_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, float *value, int maxlen, int ndx);
int fjage_param_get_double_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, double *value, int maxlen, int ndx);
int fjage_param_get_string_array(fjage_gw_t gw, fjage_aid_t aid, const char *param, char **value, int maxlen, int ndx);

In addition, I think it should be relatively easy to add support for generic messages using something similar to:

fjage_obj_t fjage_obj_create();
fjage_obj_add_int(fjage_obt_t obj, *const char key, int value);
...
fjage_msg_add_obj(fjage_msg_t msg, *const char key, fjage_obj_t value);

For fjage_param_set...() methods, it will also return an error if the ParameterRsp values do not match those that were sent (as in the case of trying to write to a read-only parameter)

It also implements base64 decoding and encoding, though encoding is only enabled for array parameters at the moment.

What I have so far is available for viewing at https://github.com/brodiealexander/fjage-rs

There are a few demos, including an implementation of datagram reception and transmission, a GetFileReq/PutFileReq utility, and an interactive remote shell.

The implementation is not ready for use, as I still have a lot of testing and cleaning up to do, and it doesn't yet support RS-232, but I did want to reach out and ask for feedback on where the project is at so far, as well as if there is any interest in adding it as a proper gateway in the future.

Thanks, Brodie

mchitre commented 1 month ago

Sounds great! Look forward to a contribution that others can use from Rust to work with fjåge based systems.