From 742cba53589ac40231895effd4b7f8e93812481b Mon Sep 17 00:00:00 2001 From: Andrew Chen Date: Mon, 6 Jan 2020 18:45:32 -0800 Subject: [PATCH] Add Comparable coercion --- lib/src/comparable.dart | 30 ++++++++++++++++- lib/src/num.dart | 6 ++-- test/comparable_test.dart | 70 +++++++++++++++++++++++++++++++-------- 3 files changed, 88 insertions(+), 18 deletions(-) diff --git a/lib/src/comparable.dart b/lib/src/comparable.dart index 3efbf7f..be96130 100644 --- a/lib/src/comparable.dart +++ b/lib/src/comparable.dart @@ -1,9 +1,37 @@ part of dartx; /// Provides comparison operators for [Comparable] types. -extension ComparableX on Comparable { +extension ComparableX> 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; } diff --git a/lib/src/num.dart b/lib/src/num.dart index 83d9e34..01314d4 100644 --- a/lib/src/num.dart +++ b/lib/src/num.dart @@ -21,7 +21,7 @@ extension NumX 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]. @@ -34,7 +34,7 @@ extension NumX 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]. /// @@ -46,7 +46,7 @@ extension NumX 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]) { diff --git a/test/comparable_test.dart b/test/comparable_test.dart index 5924e54..de94bf3 100644 --- a/test/comparable_test.dart +++ b/test/comparable_test.dart @@ -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); + }); }); }