Skip to content
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

Add Comparable coercion #30

Merged
merged 1 commit into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion lib/src/comparable.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
part of dartx;

/// Provides comparison operators for [Comparable] types.
extension ComparableX<T> on Comparable<T> {
extension ComparableX<T extends Comparable<T>> on T {
bool operator <(T other) => compareTo(other) < 0;
bool operator <=(T other) => compareTo(other) <= 0;
bool operator >(T other) => compareTo(other) > 0;
bool operator >=(T other) => compareTo(other) >= 0;

/// Ensures that this value lies in the specified range [min]..[max].
///
/// @return this value if it's in the range, or [min] if this value is
/// less than [min], or [max] if this value is greater than [max].
T coerceIn(T minimumValue, [T maximumValue]) {
if (maximumValue != null && minimumValue > maximumValue) {
throw ArgumentError('Cannot coerce value to an empty range: '
'maximum $maximumValue is less than minimum $minimumValue.');
}
if (this < minimumValue) return minimumValue;
if (maximumValue != null && this > maximumValue) return maximumValue;
return this;
}

/// Ensures that this value is not less than the specified [min].
///
/// @return this value if it's greater than or equal to the [min]
/// or the [min] otherwise.
T coerceAtLeast(T minimumValue) =>
this < minimumValue ? minimumValue : this;

/// Ensures that this value is not greater than the specified [max].
///
/// @return this value if it's less than or equal to the [max]
/// or the [max] otherwise.
T coerceAtMost(T maximumValue) =>
this > maximumValue ? maximumValue : this;
}
6 changes: 3 additions & 3 deletions lib/src/num.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension NumX<T extends num> on T {
}
if (this < minimumValue) return minimumValue;
if (maximumValue != null && this > maximumValue) return maximumValue;
return this as T;
return this;
}

/// Ensures that this value is not less than the specified [minimumValue].
Expand All @@ -34,7 +34,7 @@ extension NumX<T extends num> on T {
/// print(10.coerceAtLeast(20)) // 20
/// ```
T coerceAtLeast(T minimumValue) =>
this < minimumValue ? minimumValue : this as T;
this < minimumValue ? minimumValue : this;

/// Ensures that this value is not greater than the specified [maximumValue].
///
Expand All @@ -46,7 +46,7 @@ extension NumX<T extends num> on T {
/// print(10.coerceAtMost(20)) // 10
/// ```
T coerceAtMost(T maximumValue) =>
this > maximumValue ? maximumValue : this as T;
this > maximumValue ? maximumValue : this;

/// Converts this value to binary form.
Uint8List toBytes([Endian endian = Endian.big]) {
Expand Down
70 changes: 56 additions & 14 deletions test/comparable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,65 @@ class _WrappedInt implements Comparable<_WrappedInt> {
}

void main() {
test('comparable extension operators', () {
final one = _WrappedInt(1);
final ten = _WrappedInt(10);
final hundred = _WrappedInt(100);
group('ComparableX', () {
test('.coerceIn()', () {
DateTime.now();
expect(DateTime(1984, 11, 19).coerceIn(DateTime(1984, 11, 1)),
DateTime(1984, 11, 19));
expect(DateTime(1984, 11, 19).coerceIn(
DateTime(1984, 11, 1),
DateTime(1984, 11, 20),
), DateTime(1984, 11, 19));
expect(DateTime(1984, 10, 28).coerceIn(
DateTime(1984, 11, 1),
DateTime(1984, 11, 20),
), DateTime(1984, 11, 1));
expect(DateTime(1984, 12, 1).coerceIn(
DateTime(1984, 11, 1),
DateTime(1984, 11, 20),
), DateTime(1984, 11, 20));
expect(() => 10.coerceIn(3, 2), throwsArgumentError);
expect(() =>
DateTime.now().coerceIn(
DateTime(1984, 11, 20),
DateTime(1984, 11, 1),
), throwsArgumentError);
});

expect(one < ten, isTrue);
expect(one < one, isFalse);
test('.coerceAtLeast()', () {
expect(DateTime(1984, 11, 19).coerceAtLeast(DateTime(1984, 1, 1)),
DateTime(1984, 11, 19));
expect(DateTime(1984, 11, 19).coerceAtLeast(DateTime(1984, 1, 20)),
DateTime(1984, 11, 20));
});

expect(one <= ten, isTrue);
expect(ten <= ten, isTrue);
expect(hundred <= ten, isFalse);
test('.coerceAtMost()', () {
expect(10.coerceAtMost(12), 10);
expect(10.coerceAtMost(5), 5);
expect(DateTime(1984, 11, 19).coerceAtMost(DateTime(1984, 1, 20)),
DateTime(1984, 11, 19));
expect(DateTime(1984, 11, 19).coerceAtMost(DateTime(1984, 1, 1)),
DateTime(1984, 11, 1));
});

expect(ten >= ten, isTrue);
expect(ten >= one, isTrue);
expect(ten >= hundred, isFalse);
test('comparable extension operators', () {
final one = _WrappedInt(1);
final ten = _WrappedInt(10);
final hundred = _WrappedInt(100);

expect(ten > one, isTrue);
expect(ten > ten, isFalse);
expect(one < ten, isTrue);
expect(one < one, isFalse);

expect(one <= ten, isTrue);
expect(ten <= ten, isTrue);
expect(hundred <= ten, isFalse);

expect(ten >= ten, isTrue);
expect(ten >= one, isTrue);
expect(ten >= hundred, isFalse);

expect(ten > one, isTrue);
expect(ten > ten, isFalse);
});
});
}