Skip to content

Commit

Permalink
Merge pull request #578 from marcinjahn/allocation-free-maybe-map
Browse files Browse the repository at this point in the history
feat: add allocation-free overloads of Maybe.Map
  • Loading branch information
vkhorikov authored Dec 23, 2024
2 parents df38cd7 + 9cfd241 commit 1b13ecc
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,25 @@ public async Task Map_Task_Left_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_Task_Left_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe
.AsTask()
.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value;
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,23 @@ public async Task Map_Task_Right_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_Task_Right_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value.AsTask();
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,25 @@ public async Task Map_Task_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_Task_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe
.AsTask()
.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value.AsTask();
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,25 @@ public async Task Map_ValueTask_Left_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_ValueTask_Left_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe
.AsValueTask()
.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value;
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Threading.Tasks;
using FluentAssertions;
using CSharpFunctionalExtensions.ValueTasks;
using FluentAssertions;
using Xunit;

namespace CSharpFunctionalExtensions.Tests.MaybeTests.Extensions
Expand All @@ -27,5 +27,23 @@ public async Task Map_ValueTask_Right_returns_no_value_if_initial_maybe_is_null(

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_ValueTask_Right_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe.Map(
valueTask: (value, ctx) =>
{
ctx.Should().Be(context);
return value.AsValueTask();
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public async Task Map_ValueTask_returns_mapped_value()
{
Maybe<T> maybe = T.Value;

var maybe2 = await maybe.AsValueTask().Map(ExpectAndReturn_ValueTask(T.Value, T.Value2));
var maybe2 = await maybe
.AsValueTask()
.Map(ExpectAndReturn_ValueTask(T.Value, T.Value2));

maybe2.HasValue.Should().BeTrue();
maybe2.Value.Should().Be(T.Value2);
Expand All @@ -27,5 +29,25 @@ public async Task Map_ValueTask_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public async Task Map_ValueTask_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = await maybe
.AsValueTask()
.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value.AsValueTask();
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
}
18 changes: 18 additions & 0 deletions CSharpFunctionalExtensions.Tests/MaybeTests/Extensions/MapTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,23 @@ public void Map_returns_no_value_if_initial_maybe_is_null()

maybe2.HasValue.Should().BeFalse();
}

[Fact]
public void Map_provides_context_to_selector()
{
Maybe<T> maybe = T.Value;
var context = 5;

var maybe2 = maybe.Map(
(value, ctx) =>
{
ctx.Should().Be(context);
return value;
},
context
);

maybe2.HasValue.Should().BeTrue();
}
}
}
17 changes: 15 additions & 2 deletions CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.Left.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ namespace CSharpFunctionalExtensions
{
public static partial class MaybeExtensions
{
public static async Task<Maybe<K>> Map<T, K>(this Task<Maybe<T>> maybeTask, Func<T, K> selector)
public static async Task<Maybe<K>> Map<T, K>(
this Task<Maybe<T>> maybeTask,
Func<T, K> selector
)
{
var maybe = await maybeTask.DefaultAwait();
return maybe.Map(selector);
}

public static async Task<Maybe<K>> Map<T, K, TContext>(
this Task<Maybe<T>> maybeTask,
Func<T, TContext, K> selector,
TContext context
)
{
var maybe = await maybeTask.DefaultAwait();
return maybe.Map(selector, context);
}
}
}
}
14 changes: 13 additions & 1 deletion CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.Right.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,17 @@ public static async Task<Maybe<K>> Map<T, K>(this Maybe<T> maybe, Func<T, Task<K

return await selector(maybe.GetValueOrThrow()).DefaultAwait();
}

public static async Task<Maybe<K>> Map<T, K, TContext>(
this Maybe<T> maybe,
Func<T, TContext, Task<K>> selector,
TContext context
)
{
if (maybe.HasNoValue)
return Maybe<K>.None;

return await selector(maybe.GetValueOrThrow(), context).DefaultAwait();
}
}
}
}
17 changes: 15 additions & 2 deletions CSharpFunctionalExtensions/Maybe/Extensions/Map.Task.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ namespace CSharpFunctionalExtensions
{
public static partial class MaybeExtensions
{
public static async Task<Maybe<K>> Map<T, K>(this Task<Maybe<T>> maybeTask, Func<T, Task<K>> selector)
public static async Task<Maybe<K>> Map<T, K>(
this Task<Maybe<T>> maybeTask,
Func<T, Task<K>> selector
)
{
var maybe = await maybeTask.DefaultAwait();
return await maybe.Map(selector).DefaultAwait();
}

public static async Task<Maybe<K>> Map<T, K, TContext>(
this Task<Maybe<T>> maybeTask,
Func<T, TContext, Task<K>> selector,
TContext context
)
{
var maybe = await maybeTask.DefaultAwait();
return await maybe.Map(selector, context).DefaultAwait();
}
}
}
}
17 changes: 15 additions & 2 deletions CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.Left.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@ namespace CSharpFunctionalExtensions.ValueTasks
{
public static partial class MaybeExtensions
{
public static async ValueTask<Maybe<K>> Map<T, K>(this ValueTask<Maybe<T>> valueTask, Func<T, K> selector)
public static async ValueTask<Maybe<K>> Map<T, K>(
this ValueTask<Maybe<T>> valueTask,
Func<T, K> selector
)
{
Maybe<T> maybe = await valueTask;
return maybe.Map(selector);
}

public static async ValueTask<Maybe<K>> Map<T, K, TContext>(
this ValueTask<Maybe<T>> valueTask,
Func<T, TContext, K> selector,
TContext context
)
{
Maybe<T> maybe = await valueTask;
return maybe.Map(selector, context);
}
}
}
#endif
#endif
19 changes: 17 additions & 2 deletions CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.Right.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,28 @@ namespace CSharpFunctionalExtensions.ValueTasks
{
public static partial class MaybeExtensions
{
public static async ValueTask<Maybe<K>> Map<T, K>(this Maybe<T> maybe, Func<T, ValueTask<K>> valueTask)
public static async ValueTask<Maybe<K>> Map<T, K>(
this Maybe<T> maybe,
Func<T, ValueTask<K>> valueTask
)
{
if (maybe.HasNoValue)
return Maybe<K>.None;

return await valueTask(maybe.GetValueOrThrow());
}

public static async ValueTask<Maybe<K>> Map<T, K, TContext>(
this Maybe<T> maybe,
Func<T, TContext, ValueTask<K>> valueTask,
TContext context
)
{
if (maybe.HasNoValue)
return Maybe<K>.None;

return await valueTask(maybe.GetValueOrThrow(), context);
}
}
}
#endif
#endif
17 changes: 15 additions & 2 deletions CSharpFunctionalExtensions/Maybe/Extensions/Map.ValueTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@ namespace CSharpFunctionalExtensions.ValueTasks
{
public static partial class MaybeExtensions
{
public static async ValueTask<Maybe<K>> Map<T, K>(this ValueTask<Maybe<T>> maybeTask, Func<T, ValueTask<K>> valueTask)
public static async ValueTask<Maybe<K>> Map<T, K>(
this ValueTask<Maybe<T>> maybeTask,
Func<T, ValueTask<K>> valueTask
)
{
Maybe<T> maybe = await maybeTask;
return await maybe.Map(valueTask);
}

public static async ValueTask<Maybe<K>> Map<T, K, TContext>(
this ValueTask<Maybe<T>> maybeTask,
Func<T, TContext, ValueTask<K>> valueTask,
TContext context
)
{
Maybe<T> maybe = await maybeTask;
return await maybe.Map(valueTask, context);
}
}
}
#endif
#endif
14 changes: 13 additions & 1 deletion CSharpFunctionalExtensions/Maybe/Extensions/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,17 @@ public static Maybe<K> Map<T, K>(in this Maybe<T> maybe, Func<T, K> selector)

return selector(maybe.GetValueOrThrow());
}

public static Maybe<K> Map<T, K, TContext>(
in this Maybe<T> maybe,
Func<T, TContext, K> selector,
TContext context
)
{
if (maybe.HasNoValue)
return Maybe<K>.None;

return selector(maybe.GetValueOrThrow(), context);
}
}
}
}

0 comments on commit 1b13ecc

Please sign in to comment.