-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add nullable map and future extensions
- Loading branch information
Showing
9 changed files
with
453 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import 'dart:async'; | ||
|
||
/// Extension on `Future<T?>?` providing additional null-aware and error | ||
/// handling operations. | ||
/// | ||
/// This extension adds methods to nullable `Future<T?>` objects, allowing for | ||
/// more expressive handling of asynchronous operations that could result in | ||
/// null or error states. It includes methods for providing default values, | ||
/// handling errors gracefully, and more nuanced manipulations like executing | ||
/// alternative futures or suppressing errors. | ||
extension NullableFutureExtensions<T> on Future<T?>? { | ||
/// Returns the future's value if not null; otherwise, returns a default value | ||
Future<T> orDefault(T defaultValue) async => (await this) ?? defaultValue; | ||
|
||
/// Returns the future's value, or null if the future itself is null. | ||
Future<T?> orNull() async => await this; | ||
|
||
/// Attempts to return the future's value; on error, returns a specified value | ||
Future<T?> onErrorReturn(T value) async { | ||
try { | ||
return await this; | ||
} catch (e) { | ||
return value; | ||
} | ||
} | ||
|
||
/// Attempts to return the future's value; on error, returns null. | ||
Future<T?> onErrorReturnNull() async { | ||
try { | ||
return await this; | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
|
||
/// Returns the future's value if not null; otherwise, executes an alternative | ||
/// future. | ||
Future<T> orElse(Future<T> Function() alternative) async { | ||
return (await this) ?? await alternative(); | ||
} | ||
|
||
/// Executes a specified action when the future completes, regardless of the | ||
/// outcome. | ||
Future<T?> whenComplete(Function() action) async { | ||
try { | ||
return await this; | ||
} finally { | ||
action(); | ||
} | ||
} | ||
|
||
/// Suppresses any errors that occur during the future's execution. | ||
Future<void> ignoreErrors() async { | ||
try { | ||
await this; | ||
} catch (_) {} | ||
} | ||
|
||
/// Returns null if the future does not complete within a specified duration. | ||
Future<T?> timeoutWithNull(Duration duration) async { | ||
try { | ||
return await this?.timeout(duration); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
|
||
/// Applies a transformation to the future's value if not null. | ||
Future<R?> thenOrNull<R>(FutureOr<R?> Function(T?) onValue) async { | ||
return this == null ? null : await this!.then(onValue); | ||
} | ||
|
||
/// Attempts to return the future's value; on error, executes an onError | ||
/// function and returns null. | ||
Future<T?> catchErrorOrNull( | ||
Function(Object) onError, { | ||
bool Function(Object)? test, | ||
}) async { | ||
try { | ||
return await this; | ||
} catch (e) { | ||
if (test == null || test(e)) { | ||
onError(e); | ||
return null; | ||
} | ||
rethrow; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/// Extension on `Map<K, V>?` providing additional null-aware operations. | ||
/// | ||
/// This extension adds methods to `Map` objects that allow for more expressive | ||
/// handling of operations that could involve `null` maps. It includes methods | ||
/// for checking if a map is null or empty, providing default values, and more | ||
/// nuanced manipulations like filtering, updating, and transforming maps safely | ||
extension NullableMapExtensions<K, V> on Map<K, V>? { | ||
/// Checks if the map is null or empty. | ||
bool get isNullOrEmpty => this == null || this!.isEmpty; | ||
|
||
/// Checks if the map is not null and not empty. | ||
bool get isNotNullOrEmpty => !isNullOrEmpty; | ||
|
||
/// Returns the map if it's not null, otherwise returns the provided default | ||
/// value. | ||
Map<K, V> orDefault(Map<K, V> defaultValue) => this ?? defaultValue; | ||
|
||
/// Returns the value for the given key if it exists, otherwise returns the | ||
/// provided default value. | ||
V getOrElse(K key, V defaultValue) => this?[key] ?? defaultValue; | ||
|
||
/// Puts the default value for the given key if the key is absent in the map. | ||
void putIfAbsentOrElse(K key, V defaultValue) { | ||
if (this != null) { | ||
this!.putIfAbsent(key, () => defaultValue); | ||
} | ||
} | ||
|
||
/// Updates the value for the given key using the provided update function. | ||
void updateValue(K key, V Function(V?) update) { | ||
if (this != null) { | ||
this![key] = update(this![key]); | ||
} | ||
} | ||
|
||
/// Returns a new map containing the entries that satisfy the provided test. | ||
Map<K, V> filter(bool Function(MapEntry<K, V>) test) { | ||
if (this == null) return {}; | ||
return Map<K, V>.fromEntries(this!.entries.where(test)); | ||
} | ||
|
||
/// Maps the keys and values of the map using the provided convert function | ||
/// and returns a new map. | ||
Map<RK, RV> mapKeysAndValues<RK, RV>( | ||
MapEntry<RK, RV> Function(MapEntry<K, V>) convert, | ||
) { | ||
if (this == null) return {}; | ||
return Map<RK, RV>.fromEntries(this!.entries.map(convert)); | ||
} | ||
|
||
/// Performs an action for each key-value pair in the map. | ||
void forEachEntry(void Function(K key, V value) action) { | ||
if (this != null) { | ||
this!.forEach(action); | ||
} | ||
} | ||
|
||
/// Checks if a key exists in the map, safely handling null maps. | ||
bool containsKeyOrNull(K key) => this?.containsKey(key) ?? false; | ||
|
||
/// Checks if a value exists in the map, safely handling null maps. | ||
bool containsValueOrNull(V value) => this?.containsValue(value) ?? false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.