Skip to content

Commit 7a6e26f

Browse files
authored
Merge pull request #582 from marcinjahn/allocation-free-result-mapif
feat: add allocation-free overloads for Result.Map and Result.MapIf
2 parents b6ca7d1 + b4b398c commit 7a6e26f

30 files changed

+3086
-171
lines changed

CSharpFunctionalExtensions.Tests/ResultTests/Extensions/MapIfTests.Base.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ protected MapIfTestsBase()
1515
predicateExecuted = false;
1616
}
1717

18-
protected Func<T, T> GetAction() => value =>
19-
{
20-
actionExecuted.Should().BeFalse();
21-
value.Should().Be(T.Value);
18+
protected Func<T, T> GetAction() =>
19+
value =>
20+
{
21+
actionExecuted.Should().BeFalse();
22+
value.Should().Be(T.Value);
2223

23-
actionExecuted = true;
24-
return T.Value2;
25-
};
24+
actionExecuted = true;
25+
return T.Value2;
26+
};
2627

2728
protected Func<T, Task<T>> GetTaskAction()
2829
{
@@ -69,5 +70,7 @@ protected static Result<T, E> GetExpectedValueErrorResult(bool isSuccess, bool c
6970

7071
return Result.SuccessIf(isSuccess, T.Value2, E.Value2);
7172
}
73+
74+
protected readonly string ContextMessage = "Context data";
7275
}
7376
}

CSharpFunctionalExtensions.Tests/ResultTests/Extensions/MapIfTests.Task.Left.cs

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ public class MapIfTests_Task_Left : MapIfTestsBase
1111
[InlineData(true, false)]
1212
[InlineData(false, true)]
1313
[InlineData(false, false)]
14-
public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
14+
public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_result(
15+
bool isSuccess,
16+
bool condition
17+
)
1518
{
16-
Result<T> result = Result.SuccessIf(isSuccess, T.Value, ErrorMessage);
19+
Task<Result<T>> resultTask = Result
20+
.SuccessIf(isSuccess, T.Value, ErrorMessage)
21+
.AsTask();
1722

18-
Result<T> returned = await result.MapIf(condition, GetTaskAction());
23+
Result<T> returned = await resultTask.MapIf(condition, GetAction());
1924

2025
actionExecuted.Should().Be(isSuccess && condition);
2126
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
@@ -26,11 +31,14 @@ public async Task MapIf_Task_Left_T_executes_func_conditionally_and_returns_new_
2631
[InlineData(true, false)]
2732
[InlineData(false, true)]
2833
[InlineData(false, false)]
29-
public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
34+
public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_new_result(
35+
bool isSuccess,
36+
bool condition
37+
)
3038
{
31-
Result<T, E> result = Result.SuccessIf(isSuccess, T.Value, E.Value);
39+
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();
3240

33-
Result<T, E> returned = await result.MapIf(condition, GetTaskAction());
41+
Result<T, E> returned = await resultTask.MapIf(condition, GetAction());
3442

3543
actionExecuted.Should().Be(isSuccess && condition);
3644
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
@@ -41,11 +49,16 @@ public async Task MapIf_Task_Left_T_E_executes_func_conditionally_and_returns_ne
4149
[InlineData(true, false)]
4250
[InlineData(false, true)]
4351
[InlineData(false, false)]
44-
public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
52+
public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditionally_and_returns_new_result(
53+
bool isSuccess,
54+
bool condition
55+
)
4556
{
46-
Result<T> result = Result.SuccessIf(isSuccess, T.Value, ErrorMessage);
57+
Task<Result<T>> resultTask = Result
58+
.SuccessIf(isSuccess, T.Value, ErrorMessage)
59+
.AsTask();
4760

48-
Result<T> returned = await result.MapIf(GetValuePredicate(condition), GetTaskAction());
61+
Result<T> returned = await resultTask.MapIf(GetValuePredicate(condition), GetAction());
4962

5063
predicateExecuted.Should().Be(isSuccess);
5164
actionExecuted.Should().Be(isSuccess && condition);
@@ -57,11 +70,135 @@ public async Task MapIf_Task_Left_computes_predicate_T_executes_func_conditional
5770
[InlineData(true, false)]
5871
[InlineData(false, true)]
5972
[InlineData(false, false)]
60-
public async Task MapIf_Task_Left_computes_predicate_T_E_executes_func_conditionally_and_returns_new_result(bool isSuccess, bool condition)
73+
public async Task MapIf_Task_Left_computes_predicate_T_E_executes_func_conditionally_and_returns_new_result(
74+
bool isSuccess,
75+
bool condition
76+
)
6177
{
62-
Result<T, E> result = Result.SuccessIf(isSuccess, T.Value, E.Value);
78+
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();
6379

64-
Result<T, E> returned = await result.MapIf(GetValuePredicate(condition), GetTaskAction());
80+
Result<T, E> returned = await resultTask.MapIf(
81+
GetValuePredicate(condition),
82+
GetAction()
83+
);
84+
85+
predicateExecuted.Should().Be(isSuccess);
86+
actionExecuted.Should().Be(isSuccess && condition);
87+
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
88+
}
89+
90+
[Theory]
91+
[InlineData(true, true)]
92+
[InlineData(true, false)]
93+
[InlineData(false, true)]
94+
[InlineData(false, false)]
95+
public async Task MapIf_Task_Left_T_with_context_executes_func_conditionally_and_passes_context(
96+
bool isSuccess,
97+
bool condition
98+
)
99+
{
100+
Task<Result<T>> resultTask = Result
101+
.SuccessIf(isSuccess, T.Value, ErrorMessage)
102+
.AsTask();
103+
104+
Result<T> returned = await resultTask.MapIf(
105+
condition,
106+
(value, context) =>
107+
{
108+
context.Should().Be(ContextMessage);
109+
return GetAction()(value);
110+
},
111+
ContextMessage
112+
);
113+
114+
actionExecuted.Should().Be(isSuccess && condition);
115+
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
116+
}
117+
118+
[Theory]
119+
[InlineData(true, true)]
120+
[InlineData(true, false)]
121+
[InlineData(false, true)]
122+
[InlineData(false, false)]
123+
public async Task MapIf_Task_Left_T_E_with_context_executes_func_conditionally_and_passes_context(
124+
bool isSuccess,
125+
bool condition
126+
)
127+
{
128+
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();
129+
130+
Result<T, E> returned = await resultTask.MapIf(
131+
condition,
132+
(value, context) =>
133+
{
134+
context.Should().Be(ContextMessage);
135+
return GetAction()(value);
136+
},
137+
ContextMessage
138+
);
139+
140+
actionExecuted.Should().Be(isSuccess && condition);
141+
returned.Should().Be(GetExpectedValueErrorResult(isSuccess, condition));
142+
}
143+
144+
[Theory]
145+
[InlineData(true, true)]
146+
[InlineData(true, false)]
147+
[InlineData(false, true)]
148+
[InlineData(false, false)]
149+
public async Task MapIf_Task_Left_computes_predicate_T_with_context_executes_func_conditionally_and_passes_context(
150+
bool isSuccess,
151+
bool condition
152+
)
153+
{
154+
Task<Result<T>> resultTask = Result
155+
.SuccessIf(isSuccess, T.Value, ErrorMessage)
156+
.AsTask();
157+
158+
Result<T> returned = await resultTask.MapIf(
159+
(value, context) =>
160+
{
161+
context.Should().Be(ContextMessage);
162+
return GetValuePredicate(condition)(value);
163+
},
164+
(value, context) =>
165+
{
166+
context.Should().Be(ContextMessage);
167+
return GetAction()(value);
168+
},
169+
ContextMessage
170+
);
171+
172+
predicateExecuted.Should().Be(isSuccess);
173+
actionExecuted.Should().Be(isSuccess && condition);
174+
returned.Should().Be(GetExpectedValueResult(isSuccess, condition));
175+
}
176+
177+
[Theory]
178+
[InlineData(true, true)]
179+
[InlineData(true, false)]
180+
[InlineData(false, true)]
181+
[InlineData(false, false)]
182+
public async Task MapIf_Task_Left_computes_predicate_T_E_with_context_executes_func_conditionally_and_passes_context(
183+
bool isSuccess,
184+
bool condition
185+
)
186+
{
187+
Task<Result<T, E>> resultTask = Result.SuccessIf(isSuccess, T.Value, E.Value).AsTask();
188+
189+
Result<T, E> returned = await resultTask.MapIf(
190+
(value, context) =>
191+
{
192+
context.Should().Be(ContextMessage);
193+
return GetValuePredicate(condition)(value);
194+
},
195+
(value, context) =>
196+
{
197+
context.Should().Be(ContextMessage);
198+
return GetAction()(value);
199+
},
200+
ContextMessage
201+
);
65202

66203
predicateExecuted.Should().Be(isSuccess);
67204
actionExecuted.Should().Be(isSuccess && condition);

0 commit comments

Comments
 (0)