Skip to content

Commit

Permalink
Move unsafe methods to .Unsafe namespace; closes #8.
Browse files Browse the repository at this point in the history
Also: rename Result.Unwrap to be consistent with Maybe, as well as True Myth Typescript
  • Loading branch information
aggieben committed Jan 9, 2019
1 parent 0ace247 commit 103fb1f
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 33 deletions.
14 changes: 5 additions & 9 deletions src/TrueMyth/Maybe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace TrueMyth
{
using Unsafe;

/// <summary>
/// A static class that provides factory and extension methods for <see cref="Maybe{TValue}"/>.
/// </summary>
Expand Down Expand Up @@ -361,12 +363,6 @@ public void Match(Action<TValue> just, Action nothing)
/// </summary>
public Result<TValue, TError> ToResult<TError>(Func<TError> errFn) => this._isJust ? Result<TValue,TError>.Ok(this._value) : Result<TValue,TError>.Err(errFn());

/// <summary>
/// Get the <c>TValue</c> value out of the <c>Maybe&lt;TValue&gt;</c>. Returns the content of a <b>Just</b>, but <em>throws if the <c>Maybe</c> is <b>Nothing</b></em>.
/// Prefer to use <see cref="UnwrapOr(TValue)"/> or <see cref="UnwrapOrElse(Func{TValue})"/>.
/// </summary>
public TValue UnsafelyUnwrap() => this._isJust ? this._value : throw new InvalidOperationException($"Invalid attempt to unwrap {GetType().Name}.Nothing as {typeof(TValue).Name}");

/// <summary>
/// Safely get the <c>TValue</c> value out of the <c>Maybe&lt;TValue&gt;</c>. Returns the content of <b>Just</b> or <c>defaultValue</c> if <c>this</c> is <b>Nothing</b>.
/// This is the recommended way to get a value out of a <c>Maybe</c> most of the time.
Expand Down Expand Up @@ -457,7 +453,7 @@ public int CompareTo(Maybe<TValue> otherMaybe)
{
if (typeof(IComparable).IsAssignableFrom(typeof(TValue)))
{
var justThis = UnsafelyUnwrap() as IComparable;
var justThis = this.UnsafelyUnwrap() as IComparable;
var justThat = otherMaybe.UnsafelyUnwrap();
return justThis.CompareTo(justThat);
}
Expand Down Expand Up @@ -485,8 +481,8 @@ public int CompareTo(object obj)
#region Public Static Methods & Operators

/// <summary>
/// Equivalent of <see cref="UnsafelyUnwrap"/>. Follows usual C♯ semantics of throwing
/// an exception at runtime if the conversion is invalid.
/// Equivalent of <see cref="Unsafe.UnsafeExtensions.UnsafelyUnwrap{T}(Maybe{T})"/>. Follows usual C♯ semantics
/// of throwing an exception at runtime if the conversion is invalid.
/// </summary>
public static explicit operator TValue(Maybe<TValue> maybe) => maybe.UnsafelyUnwrap();

Expand Down
30 changes: 10 additions & 20 deletions src/TrueMyth/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

namespace TrueMyth
{
using Unsafe;

/// <summary>
/// A static class that provides factory and extension methods for <see cref="Result{TValue,TError}"/>.
/// </summary>
Expand Down Expand Up @@ -452,18 +454,6 @@ public void Match(Action<TValue> ok, Action<TError> err)
/// </summary>
public Maybe<TValue> ToMaybe() => this._isOk ? Maybe<TValue>.Of(this._value) : Maybe<TValue>.Nothing;

/// <summary>
/// Get the value out of the <c>Result</c>. Returns the content of an <b>Ok</b> but <em>throws if the result is <b>Err</b></em>.
/// Prefer to use <see cref="Unwrap(TValue)"/> or <see cref="Unwrap(Func{TError,TValue})"/>
/// </summary>
public TValue UnsafelyUnwrap() => _isOk ? _value : throw new InvalidOperationException("Invalid request to unwrap value.");

/// <summary>
/// Get the error out of the <c>Result</c>. Returns the content of an <b>Err</b>, but <em>throws if the result is <b>Ok</b></em>.
/// Prefer to use <see cref="Unwrap(Func{TError,TValue})"/>.
/// </summary>
public TError UnsafelyUnwrapErr() => !_isOk ? _error : throw new InvalidOperationException("Invalid request to unwrap error.");

/// <summary>
/// Safely get the value out of the <b>Ok</b> variant of a <c>Result</c>. This is the recommended way to get a value
/// out of a <c>Result</c> most of the time.
Expand All @@ -472,13 +462,13 @@ public void Match(Action<TValue> ok, Action<TError> err)
/// <example>
/// <code>
/// var anOk = Result&lt;int,string&gt;.Ok(1);
/// Console.WriteLine(anOk.Unwrap(0)); // 1
/// Console.WriteLine(anOk.UnwrapOr(0)); // 1
///
/// var anErr = Result&lt;int,string&gt;.Err("error");
/// Console.WriteLine(anErr.Unwrap(0)); // 0
/// Console.WriteLine(anErr.UnwrapOr(0)); // 0
/// </code>
/// </example>
public TValue Unwrap(TValue defaultValue) => this._isOk ? _value : defaultValue;
public TValue UnwrapOr(TValue defaultValue) => this._isOk ? _value : defaultValue;

/// <summary>
/// Safely get the value out of a <c>Result&lt;TValue,TError&gt;</c> by returning the wrapped value if it is <b>Ok</b>
Expand All @@ -494,13 +484,13 @@ public void Match(Action<TValue> ok, Action<TError> err)
/// var handleError = (string err) => err.Length + someOtherValue;
///
/// var anOk = Result&lt;int,string&gt;.Ok(42);
/// Console.WriteLine(anOk.Unwrap(handleError)); // 42
/// Console.WriteLine(anOk.UnwrapOrElse(handleError)); // 42
///
/// var anErr = Result&lt;int,string&gt;.Err("error");
/// Console.WriteLine(anErr.Unwrap(handleError)); // error
/// Console.WriteLine(anErr.UnwrapOrElse(handleError)); // error
/// </code>
/// </example>
public TValue Unwrap(Func<TError,TValue> elseFn) => this._isOk ? _value : elseFn(this._error);
public TValue UnwrapOrElse(Func<TError,TValue> elseFn) => this._isOk ? _value : elseFn(this._error);

#endregion

Expand Down Expand Up @@ -579,7 +569,7 @@ public int CompareTo(Result<TValue,TError> otherResult)
}
else if(typeof(IComparable).IsAssignableFrom(typeof(TError)))
{
var thisErr = UnsafelyUnwrapErr() as IComparable;
var thisErr = this.UnsafelyUnwrapErr() as IComparable;
var thatErr = otherResult.UnsafelyUnwrapErr();
return thisErr.CompareTo(thatErr);
}
Expand All @@ -596,7 +586,7 @@ public int CompareTo(Result<TValue,TError> otherResult)
}
else if (typeof(IComparable).IsAssignableFrom(typeof(TValue)))
{
var thisValue = UnsafelyUnwrap() as IComparable;
var thisValue = this.UnsafelyUnwrap() as IComparable;
var thatValue = otherResult.UnsafelyUnwrap();
return thisValue.CompareTo(thatValue);
}
Expand Down
30 changes: 30 additions & 0 deletions src/TrueMyth/Unsafe/UnsafeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using TrueMyth;

namespace TrueMyth.Unsafe
{
/// <summary>
/// Extensions to the <see cref="Maybe{T}"/> and <see cref="Result{T,Err}"/> implementations; the use of these
/// methods is discouraged by organizing them this way.
/// </summary>
public static class UnsafeExtensions
{
/// <summary>
/// Get the <c>TValue</c> value out of the <c>Maybe&lt;TValue&gt;</c>. Returns the content of a <b>Just</b>, but <em>throws if the <c>Maybe</c> is <b>Nothing</b></em>.
/// Prefer to use <see cref="Maybe{T}.UnwrapOr(T)"/> or <see cref="Maybe{T}.UnwrapOrElse(Func{T})"/>.
/// </summary>
public static T UnsafelyUnwrap<T>(this Maybe<T> maybe) => maybe.UnwrapOrElse(() => throw new InvalidOperationException($"Invalid attempt to unwrap {maybe.GetType().Name}.Nothing as {typeof(T).Name}"));

/// <summary>
/// Get the value out of the <c>Result</c>. Returns the content of an <b>Ok</b> but <em>throws if the result is <b>Err</b></em>.
/// Prefer to use <see cref="Result{T,E}.UnwrapOr(T)"/> or <see cref="Result{T,E}.UnwrapOrElse(Func{E,T})"/>
/// </summary>
public static T UnsafelyUnwrap<T,E>(this Result<T,E> result) => result.UnwrapOrElse((err) => throw new InvalidOperationException("Invalid request to unwrap value."));

/// <summary>
/// Get the error out of the <c>Result</c>. Returns the content of an <b>Err</b>, but <em>throws if the result is <b>Ok</b></em>.
/// Prefer to use <see cref="Result{T,E}.UnwrapOrElse(Func{E,T})"/>.
/// </summary>
public static E UnsafelyUnwrapErr<T,E>(this Result<T,E> result) => result.Match(t => throw new InvalidOperationException("Invalid request to unwrap error."), e => e);
}
}
1 change: 1 addition & 0 deletions test/TrueMyth.Test/MaybeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using Xunit;
using TrueMyth;
using TrueMyth.Unsafe;

namespace TrueMyth.Test
{
Expand Down
9 changes: 5 additions & 4 deletions test/TrueMyth.Test/ResultTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Xunit;
using TrueMyth;
using TrueMyth.Unsafe;

namespace TrueMyth.Test
{
Expand Down Expand Up @@ -357,7 +358,7 @@ public void UnwrapOr_Ok_Ok()
var r1 = SimpleResult.Ok(7);

// act
var r = r1.Unwrap(0);
var r = r1.UnwrapOr(0);

// assert
Assert.Equal(7, r);
Expand All @@ -370,7 +371,7 @@ public void UnwrapOr_Err_Ok()
var r1 = SimpleResult.Err("error");

// act
var r = r1.Unwrap(0);
var r = r1.UnwrapOr(0);

// assert
Assert.Equal(0, r);
Expand All @@ -384,7 +385,7 @@ public void UnwrapOrElse_Ok_Ok()
var r1 = SimpleResult.Ok(7);

// act
var r = r1.Unwrap(err => 0);
var r = r1.UnwrapOrElse(err => 0);

// assert
Assert.Equal(7, r);
Expand All @@ -397,7 +398,7 @@ public void UnwrapOrElse_Err_Ok()
var r1 = SimpleResult.Err("error");

// act
var r = r1.Unwrap(err => 0);
var r = r1.UnwrapOrElse(err => 0);

// assert
Assert.Equal(0, r);
Expand Down

0 comments on commit 103fb1f

Please sign in to comment.