-
Notifications
You must be signed in to change notification settings - Fork 54
Trap Result #151
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
Closed
Closed
Trap Result #151
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f0fd145
Added in 4 new `Result` types (`Result`, `ResultWithBacktrace`, `Resu…
martindevans f6e4031
When committing code, remember to actually include new files.
martindevans db4c237
Replaced stackoverflows in trap tests with div zero
martindevans e6f4a48
Addresses PR feedback
martindevans 528d580
Renamed `Trap` to `TrapCode` (review feedback)
martindevans 07958c5
Oops, changing tests to fit renaming of that property
martindevans File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
using System; | ||
|
||
namespace Wasmtime | ||
{ | ||
/// <summary> | ||
/// Indicates what type of result this is | ||
/// </summary> | ||
public enum ResultType | ||
{ | ||
/// <summary> | ||
/// Excecution succeeded | ||
/// </summary> | ||
Ok = 0, | ||
|
||
/// <summary> | ||
/// Result contains a trap | ||
/// </summary> | ||
Trap = 2, | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/// <summary> | ||
/// A result from a function call which may represent a Value or a Trap. If a trap happens the full backtrace is captured. | ||
/// </summary> | ||
public readonly struct ResultWithBacktrace | ||
{ | ||
/// <summary> | ||
/// Indicates what type of result this contains | ||
/// </summary> | ||
public ResultType Type { get; } | ||
|
||
private readonly TrapException? _trap; | ||
|
||
internal ResultWithBacktrace(IntPtr trap) | ||
{ | ||
Type = ResultType.Trap; | ||
_trap = TrapException.FromOwnedTrap(trap); | ||
} | ||
|
||
/// <summary> | ||
/// Get the trap associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Trap</exception> | ||
public TrapException Trap | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Trap) | ||
throw new InvalidOperationException($"Cannot get 'Trap' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _trap!; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// A result from a function call which may represent a Value or a Trap | ||
/// </summary> | ||
public readonly struct Result | ||
{ | ||
/// <summary> | ||
/// Indicates what type of result this contains | ||
/// </summary> | ||
public ResultType Type { get; } | ||
|
||
private readonly TrapCode _trap; | ||
|
||
internal Result(IntPtr trap) | ||
{ | ||
Type = ResultType.Trap; | ||
_trap = TrapException.GetTrapCode(trap); | ||
TrapException.Native.wasm_trap_delete(trap); | ||
|
||
} | ||
|
||
/// <summary> | ||
/// Get the trap associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Trap</exception> | ||
public TrapCode Trap | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Trap) | ||
throw new InvalidOperationException($"Cannot get 'Trap' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _trap; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// A result from a function call which may represent a Value or a Trap. If a trap happens the full backtrace is captured. | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public readonly struct ResultWithBacktrace<T> | ||
{ | ||
/// <summary> | ||
/// Indicates what type of result this contains | ||
/// </summary> | ||
public ResultType Type { get; } | ||
|
||
private readonly T? _value; | ||
private readonly TrapException? _trap; | ||
|
||
internal ResultWithBacktrace(T value) | ||
{ | ||
Type = ResultType.Ok; | ||
_value = value; | ||
_trap = null; | ||
} | ||
|
||
internal ResultWithBacktrace(IntPtr trap) | ||
{ | ||
Type = ResultType.Trap; | ||
_value = default; | ||
_trap = TrapException.FromOwnedTrap(trap); | ||
} | ||
|
||
/// <summary> | ||
/// Convert this result into a value, throw if it is a Trap | ||
/// </summary> | ||
/// <param name="value"></param> | ||
/// <returns></returns> | ||
/// <exception cref="TrapException">Thrown if Type == Trap</exception> | ||
/// <exception cref="ArgumentOutOfRangeException">Thrown if Type property contains an unknown value</exception> | ||
public static explicit operator T?(ResultWithBacktrace<T> value) | ||
{ | ||
switch (value.Type) | ||
{ | ||
case ResultType.Ok: | ||
return value._value; | ||
|
||
case ResultType.Trap: | ||
throw value._trap!; | ||
|
||
default: | ||
throw new ArgumentOutOfRangeException(nameof(value), $"Unknown Result Type property value '{value.Type}'"); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Get the value associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Value</exception> | ||
public T? Value | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Ok) | ||
throw new InvalidOperationException($"Cannot get 'Value' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _value; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Get the trap associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Trap</exception> | ||
public TrapException Trap | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Trap) | ||
throw new InvalidOperationException($"Cannot get 'Trap' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _trap!; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// A result from a function call which may represent a Value or a Trap | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public readonly struct Result<T> | ||
{ | ||
/// <summary> | ||
/// Indicates what type of result this contains | ||
/// </summary> | ||
public ResultType Type { get; } | ||
|
||
private readonly T? _value; | ||
private readonly TrapCode _trap; | ||
|
||
internal Result(T value) | ||
{ | ||
Type = ResultType.Ok; | ||
|
||
_value = value; | ||
_trap = default; | ||
} | ||
|
||
internal Result(IntPtr trap) | ||
{ | ||
Type = ResultType.Trap; | ||
|
||
_value = default; | ||
|
||
_trap = TrapException.GetTrapCode(trap); | ||
TrapException.Native.wasm_trap_delete(trap); | ||
|
||
} | ||
|
||
/// <summary> | ||
/// Convert this result into a value, throw if it is a Trap | ||
/// </summary> | ||
/// <param name="value"></param> | ||
/// <returns></returns> | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// <exception cref="TrapException">Thrown if Type == Trap</exception> | ||
/// <exception cref="ArgumentOutOfRangeException">Thrown if Type property contains an unknoown value</exception> | ||
public static explicit operator T?(Result<T> value) | ||
{ | ||
switch (value.Type) | ||
{ | ||
case ResultType.Ok: | ||
return value._value; | ||
|
||
case ResultType.Trap: | ||
throw new TrapException($"{value._trap} trap", null, value._trap); | ||
|
||
default: | ||
throw new ArgumentOutOfRangeException(nameof(value), $"Unknown Result Type property value '{value.Type}'"); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Get the value associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Value</exception> | ||
public T? Value | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Ok) | ||
throw new InvalidOperationException($"Cannot get 'Value' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _value; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Get the trap associated with this result | ||
/// </summary> | ||
/// <exception cref="InvalidOperationException">Thrown if this Type != Types.Trap</exception> | ||
public TrapCode Trap | ||
{ | ||
get | ||
{ | ||
if (Type != ResultType.Trap) | ||
throw new InvalidOperationException($"Cannot get 'Trap' from '{Type}' type result"); | ||
martindevans marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return _trap; | ||
} | ||
} | ||
} | ||
|
||
internal static class TypeExtensions | ||
{ | ||
internal static bool IsResult(this Type type) | ||
{ | ||
if (type == typeof(Result) || type == typeof(ResultWithBacktrace)) | ||
{ | ||
return true; | ||
} | ||
|
||
if (!type.IsGenericType) | ||
{ | ||
return false; | ||
} | ||
|
||
var gtd = type.GetGenericTypeDefinition(); | ||
return typeof(Result<>) == gtd || typeof(ResultWithBacktrace<>) == gtd; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.