Skip to content

Commit

Permalink
[mruby] Support SharedState.Set<string>() as symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
hadashiA committed Oct 21, 2024
1 parent 15aa7bf commit a6f575a
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@ public MRubySharedState(MRubyContext context)
public void Remove(string key)
{
var keyMaxBytes = System.Text.Encoding.UTF8.GetMaxByteCount(key.Length + 1);
var keyUtf8 = keyMaxBytes > 255
? new byte[keyMaxBytes]
: stackalloc byte[keyMaxBytes];
var keyUtf8 = keyMaxBytes > 255 ? new byte[keyMaxBytes] : stackalloc byte[keyMaxBytes];
var keyBytesWritten = System.Text.Encoding.UTF8.GetBytes(key, keyUtf8);
keyUtf8[keyBytesWritten] = 0; // NULL terminated

fixed (byte* keyPtr = keyUtf8)
{
NativeMethods.MrbStateRemove(context.DangerousGetPtr(), keyPtr);
NativeMethods.MrbStateRemove(context.DangerousGetPtr(), new MrbNString
{
Bytes = keyPtr,
Length = keyBytesWritten
});
}
values.TryRemove(key, out _);
}
Expand Down Expand Up @@ -67,48 +68,46 @@ public T GetOrDefault<T>(string key)
return default!;
}

public void Set(string key, int value)
public void Set(string key, int value, bool asSymbol = false)
{
Set(typeof(int), key, value);
Set(typeof(int), key, value, asSymbol);
}

public void Set(string key, float value)
public void Set(string key, float value, bool asSymbol = false)
{
Set(typeof(float), key, value);
Set(typeof(float), key, value, asSymbol);
}

public void Set(string key, bool value)
public void Set(string key, bool value, bool asSymbol = false)
{
Set(typeof(bool), key, value);
Set(typeof(bool), key, value, asSymbol);
}

public void Set(string key, string value)
public void Set(string key, string value, bool asSymbol = false)
{
Set(typeof(string), key, value);
Set(typeof(string), key, value, asSymbol);
}

void Set(Type type, string key, object boxedValue)
void Set(Type type, string key, object boxedValue, bool asSymbol)
{
var keyMaxBytes = System.Text.Encoding.UTF8.GetMaxByteCount(key.Length + 1);
var keyUtf8 = keyMaxBytes > 255
? new byte[keyMaxBytes]
: stackalloc byte[keyMaxBytes];
var keyUtf8 = keyMaxBytes > 255 ? new byte[keyMaxBytes] : stackalloc byte[keyMaxBytes];
var keyBytesWritten = System.Text.Encoding.UTF8.GetBytes(key, keyUtf8);
keyUtf8[keyBytesWritten] = 0; // NULL terminated

var typeCode = Type.GetTypeCode(type);
fixed (byte* keyPtr = keyUtf8)
{
var keyNString = new MrbNString { Bytes = keyPtr, Length = keyBytesWritten };
switch (typeCode)
{
case TypeCode.Boolean:
NativeMethods.MrbStateSetBool(context.DangerousGetPtr(), keyPtr, (bool)boxedValue);
NativeMethods.MrbStateSetBool(context.DangerousGetPtr(), keyNString, (bool)boxedValue);
break;
case TypeCode.Int32:
NativeMethods.MrbStateSetInt32(context.DangerousGetPtr(), keyPtr, (int)boxedValue);
NativeMethods.MrbStateSetInt32(context.DangerousGetPtr(), keyNString, (int)boxedValue);
break;
case TypeCode.Single:
NativeMethods.MrbStateSetFloat(context.DangerousGetPtr(), keyPtr, (float)boxedValue);
NativeMethods.MrbStateSetFloat(context.DangerousGetPtr(), keyNString, (float)boxedValue);
break;
case TypeCode.String:
{
Expand All @@ -118,10 +117,18 @@ void Set(Type type, string key, object boxedValue)
? new byte[valueMaxBytes]
: stackalloc byte[valueMaxBytes];
var valueBytesWritten = System.Text.Encoding.UTF8.GetBytes(value, valueUtf8);
valueUtf8[valueBytesWritten] = 0; // NULL terminated

fixed (byte* valuePtr = valueUtf8)
{
NativeMethods.MrbStateSetString(context.DangerousGetPtr(), keyPtr, valuePtr);
var valueNString = new MrbNString { Bytes = valuePtr, Length = valueBytesWritten };
if (asSymbol)
{
NativeMethods.MrbStateSetSymbol(context.DangerousGetPtr(), keyNString, valueNString);
}
else
{
NativeMethods.MrbStateSetString(context.DangerousGetPtr(), keyNString, valueNString);
}
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,22 @@ static unsafe class NativeMethods
public static extern void MrbCallbacksSet(MrbContextCore* context, MrbCommandHandler onCommand, MrbErrorHandler onError);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_set_int32", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateSetInt32(MrbContextCore* state, byte* key, int value);
public static extern void MrbStateSetInt32(MrbContextCore* state, MrbNString key, int value);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_set_float", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateSetFloat(MrbContextCore* state, byte* key, float value);
public static extern void MrbStateSetFloat(MrbContextCore* state, MrbNString key, float value);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_set_bool", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateSetBool(MrbContextCore* state, byte* key, bool value);
public static extern void MrbStateSetBool(MrbContextCore* state, MrbNString key, bool value);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_set_string", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateSetString(MrbContextCore* state, byte* key, byte* value);
public static extern void MrbStateSetString(MrbContextCore* state, MrbNString key, MrbNString value);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_set_symbol", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateSetSymbol(MrbContextCore* state, MrbNString key, MrbNString value);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_remove", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateRemove(MrbContextCore* state, byte* key);
public static extern void MrbStateRemove(MrbContextCore* state, MrbNString key);

[DllImport(__DllName, EntryPoint = "vitalrouter_mrb_state_clear", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void MrbStateClear(MrbContextCore* state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ public void GetSet()
Assert.That(sharedState.Get<string>("string_value"), Is.EqualTo("bar"));
Assert.That(context.Evaluate<string>("state[:string_value]"), Is.EqualTo("bar"));

sharedState.Set("symbol_value", "bra_bra", asSymbol: true);
Assert.That(sharedState.Get<string>("symbol_value"), Is.EqualTo("bra_bra"));
Assert.That(context.Evaluate<string>("state[:symbol_value]"), Is.EqualTo("bra_bra"));

sharedState.Set("int_value", 123);
Assert.That(sharedState.Get<int>("int_value"), Is.EqualTo(123));
Assert.That(context.Evaluate<int>("state[:int_value]"), Is.EqualTo(123));
Expand Down
23 changes: 14 additions & 9 deletions src/vitalrouter-mruby/src/vitalrouter-mruby.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ static void running_script_entries_remove(mrb_value fiber) {
}
}

static void shared_state_set(mrb_state *mrb, char *key, mrb_value value) {
static void shared_state_set(mrb_state *mrb, vitalrouter_nstring key, mrb_value value) {
mrb_value self = mrb_obj_value(mrb->top_self);
mrb_value state = mrb_funcall(mrb, self, "state", 0);
mrb_value sym = mrb_symbol_value(mrb_intern_cstr(mrb, key));
mrb_value sym = mrb_symbol_value(mrb_intern(mrb, (const char *)key.bytes, key.length));
mrb_funcall(mrb, state, "[]=", 2, sym, value);
}

Expand Down Expand Up @@ -116,31 +116,36 @@ extern void vitalrouter_mrb_callbacks_set(vitalrouter_mrb_ctx *ctx,
ctx->on_error = on_error;
}

extern void vitalrouter_mrb_state_set_int32(vitalrouter_mrb_ctx *ctx, char *key, int32_t value)
extern void vitalrouter_mrb_state_set_int32(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, int32_t value)
{
shared_state_set(ctx->mrb, key, mrb_fixnum_value(value));
}

extern void vitalrouter_mrb_state_set_float(vitalrouter_mrb_ctx *ctx, char *key, float_t value)
extern void vitalrouter_mrb_state_set_float(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, float_t value)
{
shared_state_set(ctx->mrb, key, mrb_float_value(ctx->mrb, value));
}

extern void vitalrouter_mrb_state_set_bool(vitalrouter_mrb_ctx *ctx, char *key, int32_t value)
extern void vitalrouter_mrb_state_set_bool(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, int32_t value)
{
shared_state_set(ctx->mrb, key, value == 0 ? mrb_false_value() : mrb_true_value());
}

extern void vitalrouter_mrb_state_set_string(vitalrouter_mrb_ctx *ctx, char *key, char *value)
extern void vitalrouter_mrb_state_set_string(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, vitalrouter_nstring value)
{
shared_state_set(ctx->mrb, key, mrb_str_new_cstr(ctx->mrb, value));
shared_state_set(ctx->mrb, key, mrb_str_new(ctx->mrb, (const char *)value.bytes, value.length));
}

extern void vitalrouter_mrb_state_remove(vitalrouter_mrb_ctx *ctx,char *key)
extern void vitalrouter_mrb_state_set_symbol(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, vitalrouter_nstring value)
{
shared_state_set(ctx->mrb, key, mrb_symbol_value(mrb_intern(ctx->mrb, (const char *)value.bytes, value.length)));
}

extern void vitalrouter_mrb_state_remove(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key)
{
mrb_value self = mrb_obj_value(ctx->mrb->top_self);
mrb_value state = mrb_funcall(ctx->mrb, self, "state", 0);
mrb_value sym = mrb_symbol_value(mrb_intern_cstr(ctx->mrb, key));
mrb_value sym = mrb_symbol_value(mrb_intern(ctx->mrb, (const char *)key.bytes, key.length));
mrb_funcall(ctx->mrb, state, "delete", 1, sym);
}

Expand Down
11 changes: 6 additions & 5 deletions src/vitalrouter-mruby/src/vitalrouter-mruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ extern void vitalrouter_mrb_callbacks_set(vitalrouter_mrb_ctx *ctx,
vitalrouter_mrb_command_cb on_command,
vitalrouter_mrb_error_cb on_error);

extern void vitalrouter_mrb_state_set_int32(vitalrouter_mrb_ctx *ctx, char *key,int32_t value);
extern void vitalrouter_mrb_state_set_float(vitalrouter_mrb_ctx *ctx, char *key, float value);
extern void vitalrouter_mrb_state_set_bool(vitalrouter_mrb_ctx *ctx, char *key,int32_t value);
extern void vitalrouter_mrb_state_set_string(vitalrouter_mrb_ctx *ctx, char *key, char *value);
extern void vitalrouter_mrb_state_remove(vitalrouter_mrb_ctx *ctx, char *key);
extern void vitalrouter_mrb_state_set_int32(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, int32_t value);
extern void vitalrouter_mrb_state_set_float(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, float value);
extern void vitalrouter_mrb_state_set_bool(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key,int32_t value);
extern void vitalrouter_mrb_state_set_string(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, vitalrouter_nstring value);
extern void vitalrouter_mrb_state_set_symbol(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key, vitalrouter_nstring value);
extern void vitalrouter_mrb_state_remove(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring key);
extern void vitalrouter_mrb_state_clear(vitalrouter_mrb_ctx *ctx);

extern mrb_value vitalrouter_mrb_load(vitalrouter_mrb_ctx *ctx, vitalrouter_nstring source);
Expand Down
1 change: 1 addition & 0 deletions src/vitalrouter-mruby/vitalrouter-mruby.def
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ EXPORTS
vitalrouter_mrb_state_set_float
vitalrouter_mrb_state_set_bool
vitalrouter_mrb_state_set_string
vitalrouter_mrb_state_set_symbol
vitalrouter_mrb_state_remove
vitalrouter_mrb_state_clear
vitalrouter_mrb_load
Expand Down

0 comments on commit a6f575a

Please sign in to comment.