Skip to content

Commit

Permalink
Merge pull request #95 from hadashiA/ku/custom-formatter
Browse files Browse the repository at this point in the history
[mruby] Support custom formatter
  • Loading branch information
hadashiA authored Oct 21, 2024
2 parents 274764e + 696c6a6 commit fe85171
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 42 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,43 @@ See the table below for the support status of mutually convertible types.
| `[Int, Int, Int, Int]` | `RectInt`, `BoundsInt`, `Color32` |
| `nil` | `T?`, `Nullable<T>` |

If you want to customize the formatting behavior, implement `IMrbValueFormatter` .

```csharp
// Example type...
public struct UserId
{
public int Value;
}

public class UserIdFormatter : IMrbValueFormatter<UserId>
{
public static readonly UserIdFormatter Instance = new();

public UserId Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerializerOptions options)
{
if (mrbValue.IsNil) return default;
retun new UserId { Value = mrbValue.IntValue };
}
}
```

To enable the custom formatter, set MrbValueSerializerOptions as follows.

```csharp
StaticCompositeResolver.Instance
.AddFormatters(UserIdFormatter.Instance) // < Yoru custom formatters
.AddResolvers(StandardResolver.Instance); // < Default behaviours
// Set serializer options to context.
var context = MRubyContext.Create(...);
context.SerializerOptions = new MrbValueSerializerOptions
{
Resolver = StaticCompositeResolver
};
```


### MRubyContext

`MRubyContext` provides several APIs for executing mruby scripts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,6 @@ namespace VitalRouter.SourceGenerator.MRuby;
[Generator]
public class VitalRouterMRubyIncrementalSourceGenerator : IIncrementalGenerator
{
class Comparer : IEqualityComparer<GeneratorAttributeSyntaxContext>
{
public static readonly Comparer Instance = new();

public bool Equals(GeneratorAttributeSyntaxContext x, GeneratorAttributeSyntaxContext y)
{
return x.TargetNode.Equals(y.TargetNode);
}

public int GetHashCode(GeneratorAttributeSyntaxContext obj)
{
return obj.TargetNode.GetHashCode();
}
}

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var commandPresetProvider = context.SyntaxProvider
Expand Down Expand Up @@ -536,7 +521,7 @@ partial class {{commandPresetTypeMeta.TypeName}}
{
if (!__Names.TryGetValue(commandName, out var index))
{
script.Fail(new ArgumentOutOfRangeException(nameof(commandName), $"No such command {commandName} in {GetType().Name}. Please use `[MRubyCommand(...)]` attribute and register it."));
script.Fail(new ArgumentOutOfRangeException(nameof(commandName), $"No such command `{commandName}` in {GetType().Name}. Please use `[MRubyCommand(...)]` attribute and register it."));
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using AOT;
using Unity.Collections;
Expand Down Expand Up @@ -102,6 +101,9 @@ public class MRubyContext : SafeHandle
[ThreadStatic]
static bool captureScriptErrors;

public static Action<Exception> GlobalErrorHandler { get; set; } = OnScriptError;
public static Action<string> GlobalLogHandler { get; set; } = UnityEngine.Debug.Log;

public static unsafe MRubyContext Create()
{
NativeMethods.MrbAllocfSet(MRubyAllocator.AllocPersistent);
Expand All @@ -120,9 +122,6 @@ public static MRubyContext Create(Router router, MRubyCommandPreset commandPrese
return context;
}

public static Action<Exception> GlobalErrorHandler { get; set; } = OnScriptError;
public static Action<string> GlobalLogHandler { get; set; } = UnityEngine.Debug.Log;

static void OnScriptError(Exception ex)
{
if (captureScriptErrors)
Expand All @@ -136,6 +135,7 @@ static void OnScriptError(Exception ex)
}

public MRubySharedState SharedState { get; }
public MrbValueSerializerOptions SerializerOptions { get; set; } = MrbValueSerializerOptions.Default;

public Router Router
{
Expand Down Expand Up @@ -187,13 +187,13 @@ public void Load(ReadOnlySpan<byte> rubySource)
public T? Evaluate<T>(string rubySource, MrbValueSerializerOptions? options = null)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(rubySource);
return Evaluate<T>(bytes);
return Evaluate<T>(bytes, options);
}

public T? Evaluate<T>(ReadOnlySpan<byte> rubySource, MrbValueSerializerOptions? options = null)
{
using var result = EvaluateUnsafe(rubySource);
return MrbValueSerializer.Deserialize<T>(result.RawValue, this, options);
return MrbValueSerializer.Deserialize<T>(result.RawValue, this, options ?? SerializerOptions);
}

public MrbValueHandle EvaluateUnsafe(string rubySource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ public struct MrbValueUnion
[StructLayout(LayoutKind.Sequential)]
public struct MrbValue
{
public MrbValueUnion Value;
MrbValueUnion value;
public MrbVtype TT;

public bool IsNil => TT == MrbVtype.MRB_TT_FALSE && Value.I == 0;
public bool IsNil => TT == MrbVtype.MRB_TT_FALSE && value.I == 0;
public long IntValue => value.I;
public double FlaotValue => value.F;

public unsafe string ToString(MRubyContext context)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public byte Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeriali
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((byte)mrbValue.Value.I);
return checked((byte)mrbValue.IntValue);
}
}

Expand All @@ -24,7 +24,7 @@ public sbyte Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerial
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((sbyte)mrbValue.Value.I);
return checked((sbyte)mrbValue.IntValue);
}
}

Expand All @@ -38,7 +38,7 @@ public char Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeriali
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((char)mrbValue.Value.I);
return checked((char)mrbValue.IntValue);
}
}

Expand All @@ -52,7 +52,7 @@ public short Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerial
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((short)mrbValue.Value.I);
return checked((short)mrbValue.IntValue);
}
}

Expand All @@ -66,7 +66,7 @@ public int Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerializ
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((int)mrbValue.Value.I);
return checked((int)mrbValue.IntValue);
}
}

Expand All @@ -80,7 +80,7 @@ public long Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeriali
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((long)mrbValue.Value.I);
return checked((long)mrbValue.IntValue);
}
}

Expand All @@ -94,7 +94,7 @@ public ushort Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeria
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((ushort)mrbValue.Value.I);
return checked((ushort)mrbValue.IntValue);
}
}

Expand All @@ -108,7 +108,7 @@ public uint Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeriali
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((uint)mrbValue.Value.I);
return checked((uint)mrbValue.IntValue);
}
}

Expand All @@ -122,7 +122,7 @@ public ulong Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerial
{
throw new MRubySerializationException($"value is not a Integer. {mrbValue.TT}");
}
return checked((ulong)mrbValue.Value.I);
return checked((ulong)mrbValue.IntValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ public float Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSerial
{
return mrbValue.TT switch
{
MrbVtype.MRB_TT_FLOAT => (float)mrbValue.Value.F,
MrbVtype.MRB_TT_INTEGER => mrbValue.Value.I,
MrbVtype.MRB_TT_FLOAT => (float)mrbValue.FlaotValue,
MrbVtype.MRB_TT_INTEGER => mrbValue.IntValue,
_ => throw new MRubySerializationException($"mrb_value cannot deserialize as float: {mrbValue.TT}")
};
}
Expand All @@ -23,8 +23,8 @@ public double Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeria
{
return mrbValue.TT switch
{
MrbVtype.MRB_TT_FLOAT => (float)mrbValue.Value.F,
MrbVtype.MRB_TT_INTEGER => mrbValue.Value.I,
MrbVtype.MRB_TT_FLOAT => (float)mrbValue.FlaotValue,
MrbVtype.MRB_TT_INTEGER => mrbValue.IntValue,
_ => throw new MRubySerializationException($"mrb_value cannot deserialize as double: {mrbValue.TT}")
};
}
Expand All @@ -38,8 +38,8 @@ public decimal Deserialize(MrbValue mrbValue, MRubyContext context, MrbValueSeri
{
return mrbValue.TT switch
{
MrbVtype.MRB_TT_FLOAT => (decimal)mrbValue.Value.F,
MrbVtype.MRB_TT_INTEGER => mrbValue.Value.I,
MrbVtype.MRB_TT_FLOAT => (decimal)mrbValue.FlaotValue,
MrbVtype.MRB_TT_INTEGER => mrbValue.IntValue,
_ => throw new MRubySerializationException($"mrb_value cannot deserialize as decimal: {mrbValue.TT}")
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public static class MrbValueSerializer
{
public static T? Deserialize<T>(MrbValue mrbValue, MRubyContext context, MrbValueSerializerOptions? options = null)
{
options ??= MrbValueSerializerOptions.Default;
options ??= context.SerializerOptions;
return options.Resolver.GetFormatterWithVerify<T>()
.Deserialize(mrbValue, context, options);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public class PrimitiveObjectFormatter : IMrbValueFormatter<object?>
case MrbVtype.MRB_TT_TRUE:
return true;
case MrbVtype.MRB_TT_INTEGER:
return (long)value.Value.I;
return value.IntValue;
case MrbVtype.MRB_TT_FLOAT:
return value.Value.F;
return value.FlaotValue;
case MrbVtype.MRB_TT_SYMBOL:
case MrbVtype.MRB_TT_STRING:
return value.ToString(context);
Expand Down
Binary file not shown.

0 comments on commit fe85171

Please sign in to comment.