Skip to content

Commit

Permalink
Merge pull request #16 from kranfix/option_utils
Browse files Browse the repository at this point in the history
Option and Result extensions
  • Loading branch information
nlfiedler authored Sep 20, 2021
2 parents 0fcd11b + 3b5fda9 commit 0f574b9
Show file tree
Hide file tree
Showing 12 changed files with 203 additions and 1 deletion.
3 changes: 3 additions & 0 deletions lib/oxidized.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,6 @@ library oxidized;
export 'src/option.dart';
export 'src/result.dart';
export 'src/unit.dart';

export 'src/option_utils/option_utils.dart';
export 'src/result_utils/result_utils.dart';
20 changes: 20 additions & 0 deletions lib/src/option_utils/option_option_flattener.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
part of 'option_utils.dart';

extension OptionOptionFlattener<T extends Object> on Option<Option<T>> {
/// Flats an option of an option.
///
/// ```dart
/// Some(Some(1)) => Some(1)
/// Some(None()) => None()
/// None() => None()
/// ```
///
/// See also:
/// - https://doc.rust-lang.org/std/option/enum.Option.html#method.flatten
Option<T> flatten() {
return match(
(option) => option,
() => None(),
);
}
}
23 changes: 23 additions & 0 deletions lib/src/option_utils/option_result_transposer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
part of 'option_utils.dart';

extension OptionResultTransposer<T extends Object, E extends Object>
on Option<Result<T, E>> {
/// Transposes the result of an option.
///
/// ```dart
/// Some(Ok(1)) => Ok(Some(1));
/// Some(Err('error message')) => Err('error message');
/// None() => Ok(None());
/// ```
///
/// See also https://doc.rust-lang.org/std/option/enum.Option.html#method.transpose
Result<Option<T>, E> transpose() {
return match(
(result) => result.match(
(value) => Ok(Some(value)),
(err) => Err(err),
),
() => Ok(None()),
);
}
}
4 changes: 4 additions & 0 deletions lib/src/option_utils/option_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'package:oxidized/oxidized.dart';

part 'option_option_flattener.dart';
part 'option_result_transposer.dart';
24 changes: 24 additions & 0 deletions lib/src/result_utils/result_option_transposer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
part of 'result_utils.dart';

extension ResultOptionTransposer<T extends Object, E extends Object>
on Result<Option<T>, E> {
/// Transposes the result to an option.
///
/// ```dart
/// Ok(None()) => None()
/// Ok(Some(val)) => Some(Ok(val))
/// Err(err) => Some(Err(err))
/// ```
///
/// See also:
/// - https://doc.rust-lang.org/std/result/enum.Result.html#method.transpose
Option<Result<T, E>> transpose() {
return match(
(option) => option.match(
(val) => Some(Ok(val)),
() => None(),
),
(err) => Some(Err(err)),
);
}
}
24 changes: 24 additions & 0 deletions lib/src/result_utils/result_result_flattener.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
part of 'result_utils.dart';

extension ResultResultFlattener<T extends Object, E extends Object>
on Result<Result<T, E>, E> {
/// Flattens a [Result<Result<T, E>, E>] into a [Result<T, E>]
///
/// ```dart
/// Ok(Ok(value)) => Ok(value)
/// Ok(Err(error)) => Err(error)
/// Err(error) => Err(error)
/// ```
///
/// See also:
/// - https://doc.rust-lang.org/std/result/enum.Result.html#method.flatten
Result<T, E> flatten() {
return match(
(result) => result.match(
(val) => Ok(val),
(err) => Err(err),
),
(err) => Err(err),
);
}
}
4 changes: 4 additions & 0 deletions lib/src/result_utils/result_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'package:oxidized/oxidized.dart';

part 'result_option_transposer.dart';
part 'result_result_flattener.dart';
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repository: https://github.com/nlfiedler/oxidized.git
issue_tracker: https://github.com/nlfiedler/oxidized/issues

environment:
sdk: '>=2.12.0 <3.0.0'
sdk: ">=2.13.0 <3.0.0"

dependencies:
equatable: ^2.0.3
Expand Down
25 changes: 25 additions & 0 deletions test/src/option_utils/option_option_flattener_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:oxidized/oxidized.dart';
import 'package:test/test.dart';

typedef OptInt = Option<int>;
typedef OptOptInt = Option<OptInt>;

void main() {
test('None().flatten() must return None', () {
final OptOptInt input = None();
final OptInt output = None();
expect(input.flatten(), equals(output));
});

test('Some(None()).flatten() must return None()', () {
final OptOptInt input = Some(None());
final OptInt output = None();
expect(input.flatten(), equals(output));
});

test('Some(Some(val)).flatten() must return Some(val)', () {
final OptOptInt input = Some(Some(1));
final OptInt output = Some(1);
expect(input.flatten(), equals(output));
});
}
25 changes: 25 additions & 0 deletions test/src/option_utils/option_result_transposer_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:oxidized/oxidized.dart';
import 'package:test/test.dart';

typedef OptRes = Option<Result<int, String>>;
typedef ResOpt = Result<Option<int>, String>;

void main() {
test('None() transpose must return Ok(None())', () {
final OptRes input = None();
final ResOpt output = Ok(None());
expect(input.transpose(), equals(output));
});

test('Some(Ok(val)) transpose must return Ok(Some(val))', () {
final OptRes input = Some(Ok(1));
final ResOpt output = Ok(Some(1));
expect(input.transpose(), equals(output));
});

test('Some(Err(val)) transpose must return Err(val)', () {
final OptRes input = Some(Err('error'));
final ResOpt output = Err('error');
expect(input.transpose(), equals(output));
});
}
25 changes: 25 additions & 0 deletions test/src/result_utils/result_option_transposer_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:oxidized/oxidized.dart';
import 'package:test/test.dart';

typedef OptRes = Option<Result<int, String>>;
typedef ResOpt = Result<Option<int>, String>;

void main() {
test('Ok(None()).transpose() must return None()', () async {
final ResOpt input = Ok(None());
final OptRes output = None();
expect(input.transpose(), output);
});

test('Ok(Some(val)).transpose() must return Some(Ok(val))', () async {
final ResOpt input = Ok(Some(1));
final OptRes output = Some(Ok(1));
expect(input.transpose(), output);
});

test('Err(err).transpose() must return Some(Err(err))', () async {
final ResOpt input = Err('error message');
final OptRes output = Some(Err('error message'));
expect(input.transpose(), output);
});
}
25 changes: 25 additions & 0 deletions test/src/result_utils/result_result_flattener_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:oxidized/oxidized.dart';
import 'package:test/test.dart';

typedef Res = Result<int, String>;
typedef ResRes = Result<Result<int, String>, String>;

void main() {
test('Ok(Ok(val).flatten() must return Ok(val)', () async {
final ResRes input = Ok(Ok(1));
final Res output = Ok(1);
expect(input.flatten(), output);
});

test('Ok(Err(err).flatten() must return Err(err)', () async {
final ResRes input = Ok(Err('error message'));
final Res output = Err('error message');
expect(input.flatten(), output);
});

test('Err(err).flatten() must return Err(err)', () async {
final ResRes input = Err('error message');
final Res output = Err('error message');
expect(input.flatten(), output);
});
}

0 comments on commit 0f574b9

Please sign in to comment.