Add Wyatt Continuous Deployment as Sub package #236
| @ -1,26 +1,21 @@ | ||||
| // // Copyright (C) 2022 WYATT GROUP | ||||
| // // Please see the AUTHORS file for details. | ||||
| // // | ||||
| // // This program is free software: you can redistribute it and/or modify | ||||
| // // it under the terms of the GNU General Public License as published by | ||||
| // // the Free Software Foundation, either version 3 of the License, or | ||||
| // // any later version. | ||||
| // // | ||||
| // // This program is distributed in the hope that it will be useful, | ||||
| // // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // // GNU General Public License for more details. | ||||
| // // | ||||
| // // You should have received a copy of the GNU General Public License | ||||
| // // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| // // ignore_for_file: avoid_positional_boolean_parameters | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:async'; | ||||
| 
 | ||||
| part 'future_result.dart'; | ||||
| part 'future_or_result.dart'; | ||||
| part 'result.dart'; | ||||
| part 'option.dart'; | ||||
| 
 | ||||
| mixin _Left<LeftType, RightType> on _EitherBase<LeftType, RightType> {} | ||||
| @ -35,7 +30,9 @@ class _EitherBaseException implements Exception { | ||||
|   String toString() => '_EitherException: $message'; | ||||
| } | ||||
| 
 | ||||
| @Deprecated('Use Dart pattern matching instead') | ||||
| abstract class _EitherBase<LeftType, RightType> { | ||||
|   @Deprecated('Use Dart pattern matching instead') | ||||
|   const _EitherBase(); | ||||
| 
 | ||||
|   bool get _isLeft => this is _Left<LeftType, RightType>; | ||||
| @ -56,20 +53,20 @@ abstract class _EitherBase<LeftType, RightType> { | ||||
|     if (U == LeftType) { | ||||
|       return _fold<LeftType>( | ||||
|         (value) => value, | ||||
|         (right) => throw const ResultException( | ||||
|         (right) => throw Exception( | ||||
|           'Illegal use. You should check left value before calling', | ||||
|         ), | ||||
|       ) as U; | ||||
|     } | ||||
|     if (U == RightType) { | ||||
|       return _fold<RightType>( | ||||
|         (left) => throw const ResultException( | ||||
|         (left) => throw Exception( | ||||
|           'Illegal use. You should check right value before calling', | ||||
|         ), | ||||
|         (value) => value, | ||||
|       ) as U; | ||||
|     } | ||||
|     throw ResultException( | ||||
|     throw Exception( | ||||
|       'Illegal use. You should use $LeftType or $RightType type', | ||||
|     ); | ||||
|   } | ||||
| @ -78,20 +75,20 @@ abstract class _EitherBase<LeftType, RightType> { | ||||
|     if (U == LeftType) { | ||||
|       return _foldAsync<LeftType>( | ||||
|         Future.value, | ||||
|         (right) => throw const ResultException( | ||||
|         (right) => throw Exception( | ||||
|           'Illegal use. You should check left value before calling', | ||||
|         ), | ||||
|       ) as Future<U>; | ||||
|     } | ||||
|     if (U == RightType) { | ||||
|       return _foldAsync<RightType>( | ||||
|         (left) => throw const ResultException( | ||||
|         (left) => throw Exception( | ||||
|           'Illegal use. You should check right value before calling', | ||||
|         ), | ||||
|         Future.value, | ||||
|       ) as Future<U>; | ||||
|     } | ||||
|     throw ResultException( | ||||
|     throw Exception( | ||||
|       'Illegal use. You should use $LeftType or $RightType type', | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| @ -41,8 +41,10 @@ class OptionException extends _EitherBaseException { | ||||
| /// if value not present) and ifPresent() (execute a block of code if the | ||||
| /// value is present). | ||||
| /// {@endtemplate} | ||||
| @Deprecated('Use Dart pattern matching instead') | ||||
| abstract class Option<T> extends _EitherBase<T, void> { | ||||
|   /// {@macro option} | ||||
|   @Deprecated('Use Dart pattern matching instead') | ||||
|   const Option._(); | ||||
| 
 | ||||
|   /// Represents the left side of [Option] class. | ||||
|  | ||||
| @ -1,325 +0,0 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| // ignore_for_file: avoid_positional_boolean_parameters | ||||
| 
 | ||||
| part of 'either_base.dart'; | ||||
| 
 | ||||
| /// {@template result_exception} | ||||
| /// [ResultException] is sometimes threw by [Result] objects. | ||||
| /// | ||||
| /// ```dart | ||||
| /// throw ResultException('Emergency failure!'); | ||||
| /// ``` | ||||
| /// {@endtemplate} | ||||
| class ResultException extends _EitherBaseException { | ||||
|   /// {@macro result_exception} | ||||
|   const ResultException(super.message); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => 'ResultException: $message'; | ||||
| } | ||||
| 
 | ||||
| /// {@template result} | ||||
| /// [Result] type is coming from functional languages where exceptions are | ||||
| /// (rightfully) considered a side-effect, and therefore not appropriate to | ||||
| /// pass domain errors. Mind the difference between different kinds of errors: | ||||
| /// Some of them belong to domain, others don't. | ||||
| /// | ||||
| /// *E.g. null reference exception or index out of bounds | ||||
| /// are not related to domain - they rather indicate a defect.* | ||||
| /// | ||||
| /// Either is defined as a generic type with two branches | ||||
| /// - success with [T] | ||||
| /// - failure with [E] | ||||
| /// | ||||
| /// It can appear in two forms, where | ||||
| /// it contains an object of [Ok], or where it contains an object | ||||
| /// of [Err]. It cannot appear in both states at once, or in none of them. | ||||
| /// Therefore, if one possesses an [Result] instance, it either contains a | ||||
| /// successfully produced result, or contains an error object. | ||||
| /// {@endtemplate} | ||||
| abstract class Result<T, E> extends _EitherBase<T, E> { | ||||
|   /// {@macro result} | ||||
|   const Result._(); | ||||
| 
 | ||||
|   /// Represents the left side of [Result] class. | ||||
|   bool get isOk => _isLeft; | ||||
| 
 | ||||
|   /// Represents the right side of [Result] class. | ||||
|   bool get isErr => _isRight; | ||||
| 
 | ||||
|   /// Get nullable [Ok] value, and discarding the error, if any. | ||||
|   T? get ok => _left; | ||||
| 
 | ||||
|   /// Get nullable [Err] value, and discarding the success value, if any. | ||||
|   E? get err => _right; | ||||
| 
 | ||||
|   /// Get [U] value, may throw an exception. | ||||
|   U unwrap<U>() => _unwrap<U>(); | ||||
| 
 | ||||
|   /// Get **async** [U] value, may throw an exception. | ||||
|   Future<U> unwrapAsync<U>() => _unwrapAsync<U>(); | ||||
| 
 | ||||
|   /// Fold [Ok] and [Err] into the value of one type | ||||
|   U fold<U>( | ||||
|     U Function(T value) valueTransformer, | ||||
|     U Function(E error) errorTransformer, | ||||
|   ) => | ||||
|       _fold( | ||||
|         (left) => valueTransformer(left), | ||||
|         (right) => errorTransformer(right), | ||||
|       ); | ||||
| 
 | ||||
|   /// Fold [Ok] and [Err] **asynchronously** into the value of one type | ||||
|   Future<U> foldAsync<U>( | ||||
|     Future<U> Function(T value) valueTransformer, | ||||
|     Future<U> Function(E error) errorTransformer, | ||||
|   ) => | ||||
|       _foldAsync( | ||||
|         (left) => valueTransformer(left), | ||||
|         (right) => errorTransformer(right), | ||||
|       ); | ||||
| 
 | ||||
|   /// Swap [Ok] and [Err] | ||||
|   Result<E, T> swap() => fold(Err.new, Ok.new); | ||||
| 
 | ||||
|   /// Returns [res] if the [Result] is [Ok], otherwise returns | ||||
|   /// the [Err] value of this. | ||||
|   Result<U, E> and<U>(Result<U, E> res) => _and<U>(res) as Result<U, E>; | ||||
| 
 | ||||
|   /// Returns [res] if the [Result] is [Err], otherwise returns | ||||
|   /// the [Ok] value of this. | ||||
|   Result<T, F> or<F>(Result<T, F> res) => _or<F>(res) as Result<T, F>; | ||||
| 
 | ||||
|   /// Returns true if the result is an [Ok] or [Err] value containing | ||||
|   /// the given value/error. | ||||
|   bool contains<U>(U x) => _contains(x); | ||||
| 
 | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on [Err] with | ||||
|   /// its content. | ||||
|   T expect(String msg) => _expect(msg); | ||||
| 
 | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on [Ok] with | ||||
|   /// its content. | ||||
|   E expectErr(String msg) => _expectErr(msg); | ||||
| 
 | ||||
|   /// Maps a [Result<T, E>] to [Result<U, E>] by applying a function to a | ||||
|   /// contained [Ok] value, leaving an [Err] value untouched. | ||||
|   Result<U, E> map<U>(U Function(T value) mapper) => | ||||
|       _map(mapper) as Result<U, E>; | ||||
| 
 | ||||
|   /// Maps a [Result<T, E>] to [Result<U, E>] by applying an **async** function | ||||
|   /// to a contained [Ok] value, leaving an [Err] value untouched. | ||||
|   Future<Result<U, E>> mapAsync<U>(Future<U> Function(T value) mapper) => | ||||
|       _mapAsync(mapper) as Future<Result<U, E>>; | ||||
| 
 | ||||
|   /// Maps a [Result<T, E>] to [Result<T, F>] by applying a function to a | ||||
|   /// contained [Err] value, leaving an [Ok] value untouched. | ||||
|   Result<T, F> mapErr<F>(F Function(E error) mapper) => | ||||
|       _mapErr(mapper) as Result<T, F>; | ||||
| 
 | ||||
|   /// Maps a [Result<T, E>] to [Result<U, E>] by applying an **async** function | ||||
|   /// to a contained [Err] value, leaving an [Ok] value untouched. | ||||
|   Future<Result<T, F>> mapErrAsync<F>(Future<F> Function(E error) mapper) => | ||||
|       _mapErrAsync(mapper) as Future<Result<T, F>>; | ||||
| 
 | ||||
|   /// Transforms a [Result<T, E>] to [Result<U, F>] by applying functions to | ||||
|   /// contained [Ok] and [Err] values. | ||||
|   Result<U, F> either<U, F>( | ||||
|     U Function(T value) valueTransformer, | ||||
|     F Function(E error) errorTransformer, | ||||
|   ) => | ||||
|       _either<U, F>(valueTransformer, errorTransformer) as Result<U, F>; | ||||
| 
 | ||||
|   /// Transforms a [Result<T, E>] to [Result<U, F>] by applying **async** | ||||
|   /// functions to contained [Ok] and [Err] values. | ||||
|   Future<Result<U, F>> eitherAsync<U, F>( | ||||
|     Future<U> Function(T value) valueTransformer, | ||||
|     Future<F> Function(E error) errorTransformer, | ||||
|   ) => | ||||
|       _eitherAsync<U, F>(valueTransformer, errorTransformer) | ||||
|           as Future<Result<U, F>>; | ||||
| 
 | ||||
|   /// Constructs a new [Result] from a function that might throw | ||||
|   static Result<T, E> tryCatch<T, E, Error extends Object>( | ||||
|     T Function() tryFn, | ||||
|     E Function(Error error) onError, | ||||
|   ) { | ||||
|     try { | ||||
|       return Ok(tryFn()); | ||||
|     } on Error catch (e) { | ||||
|       return Err(onError(e)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Constructs a new [Result] from an **async** function that might throw | ||||
|   static Future<Result<T, E>> tryCatchAsync<T, E, Error extends Object>( | ||||
|     Future<T> Function() tryFn, | ||||
|     E Function(Error error) onError, | ||||
|   ) async { | ||||
|     try { | ||||
|       return Ok(await tryFn()); | ||||
|     } on Error catch (e) { | ||||
|       return Err(onError(e)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// If the condition is satify then return [value] in | ||||
|   /// [Ok] else [error] in [Err] | ||||
|   static Result<T, E> conditional<T, E>( | ||||
|     bool test, | ||||
|     T value, | ||||
|     E error, | ||||
|   ) => | ||||
|       test ? Ok(value) : Err(error); | ||||
| 
 | ||||
|   /// If the condition is satify then return *command* [value] | ||||
|   /// in [Ok] else [error] in [Err] | ||||
|   static Result<T, E> conditionalLazy<T, E>( | ||||
|     bool test, | ||||
|     T Function() value, | ||||
|     E Function() error, | ||||
|   ) => | ||||
|       test ? Ok(value()) : Err(error()); | ||||
| } | ||||
| 
 | ||||
| /// {@template ok} | ||||
| /// Contains the success value of a [Result] | ||||
| /// | ||||
| /// {@macro result} | ||||
| /// {@endtemplate} | ||||
| class Ok<T, E> extends Result<T, E> with _Left<T, E> { | ||||
|   /// {@macro ok} | ||||
|   const Ok(this.value) : super._(); | ||||
|   final T value; | ||||
| 
 | ||||
|   @override | ||||
|   U _fold<U>(U Function(T left) fnL, U Function(E right) fnR) => fnL(value); | ||||
| 
 | ||||
|   @override | ||||
|   Future<U> _foldAsync<U>( | ||||
|     Future<U> Function(T left) fnL, | ||||
|     Future<U> Function(E right) fnR, | ||||
|   ) => | ||||
|       fnL(value); | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, E> _and<U>(_EitherBase<U, E> res) => res as Result<U, E>; | ||||
| 
 | ||||
|   @override | ||||
|   Result<T, F> _or<F>(_EitherBase<T, F> res) => this as Result<T, F>; | ||||
| 
 | ||||
|   @override | ||||
|   bool _contains<U>(U x) => value == x; | ||||
| 
 | ||||
|   @override | ||||
|   T _expect(String msg) => value; | ||||
| 
 | ||||
|   @override | ||||
|   E _expectErr(String msg) => throw ResultException('$msg: $value'); | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, E> _map<U>(U Function(T value) mapper) => Ok(mapper(value)); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<U, E>> _mapAsync<U>(Future<U> Function(T value) mapper) => | ||||
|       mapper(value).then(Ok.new); | ||||
| 
 | ||||
|   @override | ||||
|   Result<T, F> _mapErr<F>(F Function(E error) mapper) => Ok(value); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<T, F>> _mapErrAsync<F>(Future<F> Function(E error) mapper) => | ||||
|       Future.value(Ok(value)); | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, F> _either<U, F>( | ||||
|     U Function(T value) fnL, | ||||
|     F Function(E error) fnR, | ||||
|   ) => | ||||
|       Ok(fnL(value)); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<U, F>> _eitherAsync<U, F>( | ||||
|     Future<U> Function(T value) fnL, | ||||
|     Future<F> Function(E error) fnR, | ||||
|   ) => | ||||
|       fnL(value).then(Ok.new); | ||||
| } | ||||
| 
 | ||||
| /// {@template err} | ||||
| /// Contains the error value of a [Result] | ||||
| /// | ||||
| /// {@macro result} | ||||
| /// {@endtemplate} | ||||
| class Err<T, E> extends Result<T, E> with _Right<T, E> { | ||||
|   /// {@macro err} | ||||
|   const Err(this.error) : super._(); | ||||
|   final E error; | ||||
| 
 | ||||
|   @override | ||||
|   U _fold<U>(U Function(T left) fnL, U Function(E right) fnR) => fnR(error); | ||||
| 
 | ||||
|   @override | ||||
|   Future<U> _foldAsync<U>( | ||||
|     Future<U> Function(T left) fnL, | ||||
|     Future<U> Function(E right) fnR, | ||||
|   ) => | ||||
|       fnR(error); | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, E> _and<U>(_EitherBase<U, E> res) => this as Result<U, E>; | ||||
|   @override | ||||
|   Result<T, F> _or<F>(_EitherBase<T, F> res) => res as Result<T, F>; | ||||
| 
 | ||||
|   @override | ||||
|   bool _contains<U>(U x) => error == x; | ||||
| 
 | ||||
|   @override | ||||
|   T _expect(String msg) => throw ResultException('$msg: $error'); | ||||
| 
 | ||||
|   @override | ||||
|   E _expectErr(String msg) => error; | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, E> _map<U>(U Function(T value) mapper) => Err(error); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<U, E>> _mapAsync<U>(Future<U> Function(T value) mapper) => | ||||
|       Future.value(Err(error)); | ||||
| 
 | ||||
|   @override | ||||
|   Result<T, F> _mapErr<F>(F Function(E error) mapper) => Err(mapper(error)); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<T, F>> _mapErrAsync<F>(Future<F> Function(E error) mapper) => | ||||
|       mapper(error).then(Err.new); | ||||
| 
 | ||||
|   @override | ||||
|   Result<U, F> _either<U, F>( | ||||
|     U Function(T value) fnL, | ||||
|     F Function(E error) fnR, | ||||
|   ) => | ||||
|       Err(fnR(error)); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Result<U, F>> _eitherAsync<U, F>( | ||||
|     Future<U> Function(T value) fnL, | ||||
|     Future<F> Function(E error) fnR, | ||||
|   ) => | ||||
|       fnR(error).then(Err.new); | ||||
| } | ||||
| @ -37,13 +37,10 @@ extension IterableIntExtension on Iterable<int>? { | ||||
|     switch (to) { | ||||
|       case Encoding.utf8: | ||||
|         str = utf8.decode(this?.toList() ?? []); | ||||
|         break; | ||||
|       case Encoding.utf16: | ||||
|         str = String.fromCharCodes(this ?? []); | ||||
|         break; | ||||
|       case Encoding.base64: | ||||
|         str = base64.encode(this?.toList() ?? []); | ||||
|         break; | ||||
|       case Encoding.base16: | ||||
|         str = List.generate( | ||||
|           (this ?? []).length, | ||||
|  | ||||
| @ -33,13 +33,10 @@ extension StringExtension on String? { | ||||
|     switch (from) { | ||||
|       case Encoding.utf8: | ||||
|         bytes = utf8.encode(this ?? '').toTypedList(); | ||||
|         break; | ||||
|       case Encoding.utf16: | ||||
|         bytes = (this ?? '').runes.toList().toTypedList(); | ||||
|         break; | ||||
|       case Encoding.base64: | ||||
|         bytes = base64.decode(this ?? ''); | ||||
|         break; | ||||
|       case Encoding.base16: | ||||
|         assert( | ||||
|           (this ?? '').length.isEven, | ||||
|  | ||||
| @ -21,8 +21,10 @@ extension PairExtension<T> on Pair<T, T> { | ||||
| /// {@template pair} | ||||
| /// [Pair] is a simple object which contains pair of two values. | ||||
| /// {@endtemplate} | ||||
| @Deprecated('Use Dart built-in record type instead') | ||||
| class Pair<L, R> { | ||||
|   /// {@macro pair} | ||||
|   @Deprecated('Use Dart built-in record type instead') | ||||
|   const Pair(this.left, this.right); | ||||
|   final L? left; | ||||
|   final R? right; | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| @ -14,7 +14,9 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| part of 'either_base.dart'; | ||||
| import 'dart:async'; | ||||
| 
 | ||||
| import 'package:wyatt_type_utils/src/result/result.dart'; | ||||
| 
 | ||||
| extension FutureOrResultExtension<T, E> on FutureOr<Result<T, E>> { | ||||
|   /// Represents the left side of [Result] class. | ||||
| @ -72,13 +74,13 @@ extension FutureOrResultExtension<T, E> on FutureOr<Result<T, E>> { | ||||
|   Future<bool> contains<U>(U x) => | ||||
|       Future.value(this).then((result) => result.contains(x)); | ||||
| 
 | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on [Err] with | ||||
|   /// its content. | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on | ||||
|   /// [Err] with its content. | ||||
|   Future<T> expect(String msg) => | ||||
|       Future.value(this).then((result) => result.expect(msg)); | ||||
| 
 | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on [Ok] with | ||||
|   /// its content. | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on | ||||
|   /// [Ok] with its content. | ||||
|   Future<E> expectErr(String msg) => | ||||
|       Future.value(this).then((result) => result.expectErr(msg)); | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| @ -14,7 +14,7 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| part of 'either_base.dart'; | ||||
| import 'package:wyatt_type_utils/src/result/result.dart'; | ||||
| 
 | ||||
| extension FutureResultExtension<T, E> on Future<Result<T, E>> { | ||||
|   /// Represents the left side of [Result] class. | ||||
| @ -62,12 +62,12 @@ extension FutureResultExtension<T, E> on Future<Result<T, E>> { | ||||
|   /// the given value/error. | ||||
|   Future<bool> contains<U>(U x) => then((result) => result.contains(x)); | ||||
| 
 | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on [Err] with | ||||
|   /// its content. | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on | ||||
|   /// [Err] with its content. | ||||
|   Future<T> expect(String msg) => then((result) => result.expect(msg)); | ||||
| 
 | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on [Ok] with | ||||
|   /// its content. | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on | ||||
|   /// [Ok] with its content. | ||||
|   Future<E> expectErr(String msg) => then((result) => result.expectErr(msg)); | ||||
| 
 | ||||
|   /// Maps a [Result<T, E>] to [Result<U, E>] by applying a function to a | ||||
							
								
								
									
										346
									
								
								packages/wyatt_type_utils/lib/src/result/result.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								packages/wyatt_type_utils/lib/src/result/result.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,346 @@ | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| // ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes | ||||
| 
 | ||||
| import 'package:sealed_result/sealed_result.dart' as sealed; | ||||
| 
 | ||||
| export 'future_or_result.dart'; | ||||
| export 'future_result.dart'; | ||||
| 
 | ||||
| class ResultException extends sealed.ResultException { | ||||
|   const ResultException(String super.message); | ||||
| } | ||||
| 
 | ||||
| /// {@template result} | ||||
| /// [Result] type is coming from functional languages where exceptions are | ||||
| /// (rightfully) considered a side-effect, and therefore not appropriate to | ||||
| /// pass domain errors. Mind the difference between different kinds of errors: | ||||
| /// Some of them belong to domain, others don't. | ||||
| /// | ||||
| /// *E.g. null reference exception or index out of bounds | ||||
| /// are not related to domain - they rather indicate a defect.* | ||||
| /// | ||||
| /// Either is defined as a generic type with two branches | ||||
| /// - success with [Success] | ||||
| /// - failure with [Failure] | ||||
| /// | ||||
| /// It can appear in two forms, where | ||||
| /// it contains an object of [Ok], or where it contains an object | ||||
| /// of [Err]. It cannot appear in both states at once, or in none of them. | ||||
| /// Therefore, if one possesses an [Result] instance, it either contains a | ||||
| /// successfully produced result, or contains an error object. | ||||
| /// {@endtemplate} | ||||
| class Result<Success, Failure> { | ||||
|   /// {@macro result} | ||||
|   const Result._(this._result); | ||||
| 
 | ||||
|   factory Result.ok(Success value) => Ok(value); | ||||
|   factory Result.err(Failure value) => Err(value); | ||||
|   factory Result.error(Failure value) => Err(value); | ||||
|   factory Result.success(Success value) => Ok(value); | ||||
|   factory Result.failure(Failure value) => Err(value); | ||||
| 
 | ||||
|   final sealed.Result<Success, Failure> _result; | ||||
| 
 | ||||
|   /// Represents the left side of [Result] class. | ||||
|   bool get isOk => _result.isOk; | ||||
| 
 | ||||
|   /// Represents the right side of [Result] class. | ||||
|   bool get isErr => _result.isErr; | ||||
| 
 | ||||
|   /// Get nullable [Ok] value, and discarding the error, if any. | ||||
|   Success? get ok => _result.ok; | ||||
| 
 | ||||
|   /// Get nullable [Err] value, and discarding the success value, if any. | ||||
|   Failure? get err => _result.err; | ||||
| 
 | ||||
|   /// Get [U] value, may throw an exception. | ||||
|   U unwrap<U>() { | ||||
|     if (U == Success) { | ||||
|       return fold<Success>( | ||||
|         (value) => value, | ||||
|         (right) => throw const ResultException( | ||||
|           'Illegal use. You should check left value before calling', | ||||
|         ), | ||||
|       ) as U; | ||||
|     } | ||||
|     if (U == Failure) { | ||||
|       return fold<Failure>( | ||||
|         (left) => throw const ResultException( | ||||
|           'Illegal use. You should check right value before calling', | ||||
|         ), | ||||
|         (value) => value, | ||||
|       ) as U; | ||||
|     } | ||||
|     throw ResultException( | ||||
|       'Illegal use. You should use $Success or $Failure type', | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /// Get **async** [U] value, may throw an exception. | ||||
|   Future<U> unwrapAsync<U>() { | ||||
|     if (U == Success) { | ||||
|       return foldAsync<Success>( | ||||
|         Future.value, | ||||
|         (right) => throw const ResultException( | ||||
|           'Illegal use. You should check left value before calling', | ||||
|         ), | ||||
|       ) as Future<U>; | ||||
|     } | ||||
|     if (U == Failure) { | ||||
|       return foldAsync<Failure>( | ||||
|         (left) => throw const ResultException( | ||||
|           'Illegal use. You should check right value before calling', | ||||
|         ), | ||||
|         Future.value, | ||||
|       ) as Future<U>; | ||||
|     } | ||||
|     throw ResultException( | ||||
|       'Illegal use. You should use $Success or $Failure type', | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /// Fold [Ok] and [Err] into the value of one type | ||||
|   U fold<U>( | ||||
|     U Function(Success value) valueTransformer, | ||||
|     U Function(Failure error) errorTransformer, | ||||
|   ) => | ||||
|       _result.fold( | ||||
|         (ok) => valueTransformer(ok), | ||||
|         (err) => errorTransformer(err), | ||||
|       ); | ||||
| 
 | ||||
|   /// Fold [Ok] and [Err] **asynchronously** into the value of one type | ||||
|   Future<U> foldAsync<U>( | ||||
|     Future<U> Function(Success value) valueTransformer, | ||||
|     Future<U> Function(Failure error) errorTransformer, | ||||
|   ) => | ||||
|       _result.foldAsync( | ||||
|         (ok) => valueTransformer(ok), | ||||
|         (err) => errorTransformer(err), | ||||
|       ); | ||||
| 
 | ||||
|   /// Swap [Ok] and [Err] | ||||
|   Result<Failure, Success> swap() => fold( | ||||
|         Err.new, | ||||
|         Ok.new, | ||||
|       ); | ||||
| 
 | ||||
|   /// Returns [res] if the [Result] is [Ok], otherwise returns | ||||
|   /// the [Err] value of this. | ||||
|   Result<U, Failure> and<U>(Result<U, Failure> res) => Result._( | ||||
|         _result.and(res._result), | ||||
|       ); | ||||
| 
 | ||||
|   /// Returns [res] if the [Result] is [Err], otherwise returns | ||||
|   /// the [Ok] value of this. | ||||
|   Result<Success, F> or<F>(Result<Success, F> res) => Result._( | ||||
|         _result.or(res._result), | ||||
|       ); | ||||
| 
 | ||||
|   /// Returns true if the result is an [Ok] or [Err] value containing | ||||
|   /// the given value/error. | ||||
|   bool contains<U>(U x) { | ||||
|     if (x is Success) { | ||||
|       return _result.contains(x); | ||||
|     } else if (x is Failure) { | ||||
|       return _result.containsErr(x); | ||||
|     } else { | ||||
|       throw ArgumentError('The value must be of type Success or Failure'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Returns the contained [Ok] value. Throw [ResultException] on [Err] | ||||
|   /// with its content. | ||||
|   Success expect(String msg) { | ||||
|     try { | ||||
|       return _result.expect(msg); | ||||
|     } on sealed.ResultException catch (e) { | ||||
|       throw ResultException(e.message.toString()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Returns the contained [Err] value. Throw [ResultException] on [Ok] | ||||
|   /// with its content. | ||||
|   Failure expectErr(String msg) { | ||||
|     try { | ||||
|       return _result.expectErr(msg); | ||||
|     } on sealed.ResultException catch (e) { | ||||
|       throw ResultException(e.message.toString()); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Maps a [Result<Success, Failure>] to [Result<U, Failure>] by applying a | ||||
|   /// function to a contained [Ok] value, leaving an [Err] value untouched. | ||||
|   Result<U, Failure> map<U>(U Function(Success value) mapper) => | ||||
|       Result._(_result.map(mapper)); | ||||
| 
 | ||||
|   /// Maps a [Result<Success, Failure>] to [Result<U, Failure>] by applying | ||||
|   /// an **async** function to a contained [Ok] value, leaving an [Err] | ||||
|   /// value untouched. | ||||
|   Future<Result<U, Failure>> mapAsync<U>( | ||||
|     Future<U> Function(Success value) mapper, | ||||
|   ) async { | ||||
|     final result = await _result.mapAsync(mapper); | ||||
|     return Result._(result); | ||||
|   } | ||||
| 
 | ||||
|   /// Maps a [Result<Success, Failure>] to [Result<Success, F>] by applying a | ||||
|   /// function to a contained [Err] value, leaving an [Ok] value untouched. | ||||
|   Result<Success, F> mapErr<F>(F Function(Failure error) mapper) => | ||||
|       Result._(_result.mapErr(mapper)); | ||||
| 
 | ||||
|   /// Maps a [Result<Success, Failure>] to [Result<U, Failure>] by applying | ||||
|   /// an **async** function to a contained [Err] value, leaving an [Ok] | ||||
|   /// value untouched. | ||||
|   Future<Result<Success, F>> mapErrAsync<F>( | ||||
|     Future<F> Function(Failure error) mapper, | ||||
|   ) async { | ||||
|     final result = await _result.mapErrAsync(mapper); | ||||
|     return Result._(result); | ||||
|   } | ||||
| 
 | ||||
|   /// Transforms a [Result<Success, Failure>] to [Result<U, F>] by applying | ||||
|   /// functions to contained [Ok] and [Err] values. | ||||
|   Result<U, F> either<U, F>( | ||||
|     U Function(Success value) valueTransformer, | ||||
|     F Function(Failure error) errorTransformer, | ||||
|   ) => | ||||
|       Result._( | ||||
|         _result | ||||
|             .map( | ||||
|               valueTransformer, | ||||
|             ) | ||||
|             .mapErr( | ||||
|               errorTransformer, | ||||
|             ), | ||||
|       ); | ||||
| 
 | ||||
|   /// Transforms a [Result<Success, Failure>] to [Result<U, F>] by | ||||
|   /// applying **async** functions to contained [Ok] and [Err] values. | ||||
|   Future<Result<U, F>> eitherAsync<U, F>( | ||||
|     Future<U> Function(Success value) valueTransformer, | ||||
|     Future<F> Function(Failure error) errorTransformer, | ||||
|   ) => | ||||
|       _result | ||||
|           .mapAsync( | ||||
|             valueTransformer, | ||||
|           ) | ||||
|           .mapErrAsync( | ||||
|             errorTransformer, | ||||
|           ) | ||||
|           .then(Result._); | ||||
| 
 | ||||
|   /// Constructs a new [Result] from a function that might throw | ||||
|   static Result<Success, Failure> | ||||
|       tryCatch<Success, Failure, Error extends Object>( | ||||
|     Success Function() tryFn, | ||||
|     Failure Function(Error error) onError, | ||||
|   ) { | ||||
|     try { | ||||
|       return Ok(tryFn()); | ||||
|     } on Error catch (e) { | ||||
|       return Err(onError(e)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// Constructs a new [Result] from an **async** function that might throw | ||||
|   static Future<Result<Success, Failure>> | ||||
|       tryCatchAsync<Success, Failure, Error extends Object>( | ||||
|     Future<Success> Function() tryFn, | ||||
|     Failure Function(Error error) onError, | ||||
|   ) async { | ||||
|     try { | ||||
|       return Ok(await tryFn()); | ||||
|     } on Error catch (e) { | ||||
|       return Err(onError(e)); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /// If the condition is satify then return [value] in | ||||
|   /// [Ok] else [error] in [Err] | ||||
|   static Result<Success, Failure> conditional<Success, Failure>( | ||||
|     Success value, | ||||
|     Failure error, { | ||||
|     required bool test, | ||||
|   }) => | ||||
|       test ? Ok(value) : Err(error); | ||||
| 
 | ||||
|   /// If the condition is satify then return *command* [value] | ||||
|   /// in [Ok] else [error] in [Err] | ||||
|   static Result<Success, Failure> conditionalLazy<Success, Failure>( | ||||
|     Success Function() value, | ||||
|     Failure Function() error, | ||||
|     bool Function() predicate, | ||||
|   ) => | ||||
|       predicate.call() ? Ok(value()) : Err(error()); | ||||
| 
 | ||||
|   @override | ||||
|   int get hashCode => _result.hashCode; | ||||
| 
 | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     if (identical(this, other)) { | ||||
|       return true; | ||||
|     } | ||||
|     return other is Result<Success, Failure> && other._result == _result; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| final class Ok<Success, Failure> extends Result<Success, Failure> { | ||||
|   Ok(this.ok) : super._(sealed.Ok(ok)); | ||||
| 
 | ||||
|   @override | ||||
|   final Success ok; | ||||
| 
 | ||||
|   @override | ||||
|   bool get isErr => false; | ||||
| 
 | ||||
|   @override | ||||
|   bool get isOk => true; | ||||
| 
 | ||||
|   @override | ||||
|   Failure? get err => null; | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => switch (ok) { | ||||
|         null => 'Ok(null)', | ||||
|         Future() => 'Ok(${ok.runtimeType})', | ||||
|         _ => 'Ok($ok)', | ||||
|       }; | ||||
| } | ||||
| 
 | ||||
| final class Err<Success, Failure> extends Result<Success, Failure> { | ||||
|   Err(this.err) : super._(sealed.Err(err)); | ||||
| 
 | ||||
|   @override | ||||
|   final Failure err; | ||||
| 
 | ||||
|   @override | ||||
|   bool get isErr => true; | ||||
| 
 | ||||
|   @override | ||||
|   bool get isOk => false; | ||||
| 
 | ||||
|   @override | ||||
|   Success? get ok => null; | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => switch (err) { | ||||
|         _ => 'Err($err)', | ||||
|       }; | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Copyright (C) 2024 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| @ -17,3 +17,4 @@ | ||||
| export 'either/either_base.dart'; | ||||
| export 'extensions/extensions.dart'; | ||||
| export 'pair/pair.dart'; | ||||
| export 'result/result.dart'; | ||||
|  | ||||
| @ -6,11 +6,14 @@ version: 0.0.5 | ||||
| publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | ||||
| 
 | ||||
| environment: | ||||
|   sdk: ">=2.17.0 <3.0.0" | ||||
|   sdk: "^3.0.0" | ||||
| 
 | ||||
| dependencies: | ||||
|   sealed_result: ^3.0.0 | ||||
| 
 | ||||
| dev_dependencies: | ||||
|   test: ^1.22.0 | ||||
| 
 | ||||
|   wyatt_analysis: | ||||
|     hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub | ||||
|     version: ^2.5.0 | ||||
|     version: ^2.6.1 | ||||
|  | ||||
| @ -21,85 +21,83 @@ void main() { | ||||
|   group('Result<T,E>', () { | ||||
|     test('`isOk` returns true on Ok value', () { | ||||
|       expect( | ||||
|         const Ok<void, void>(null).isOk, | ||||
|         Ok<void, void>(null).isOk, | ||||
|         true, | ||||
|       ); | ||||
|       expect( | ||||
|         const Err<void, void>(null).isOk, | ||||
|         Err<void, void>(null).isOk, | ||||
|         false, | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('`isErr` returns true on Err value', () { | ||||
|       expect( | ||||
|         const Ok<void, void>(null).isErr, | ||||
|         Ok<void, void>(null).isErr, | ||||
|         false, | ||||
|       ); | ||||
|       expect( | ||||
|         const Err<void, void>(null).isErr, | ||||
|         Err<void, void>(null).isErr, | ||||
|         true, | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('`ok` returns value on Ok value', () { | ||||
|       const Result<int, String> x = Ok(2); | ||||
|       final Result<int, String> x = Ok(2); | ||||
|       expect(x.ok, 2); | ||||
|       expect(x.err, null); | ||||
|     }); | ||||
| 
 | ||||
|     test('`err` returns error on Err value', () { | ||||
|       const Result<int, String> x = Err('error'); | ||||
|       final Result<int, String> x = Err('error'); | ||||
|       expect(x.ok, null); | ||||
|       expect(x.err, 'error'); | ||||
|     }); | ||||
| 
 | ||||
|     test('unwrap() returns value on Ok value', () { | ||||
|       const Result<int, String> x = Ok(2); | ||||
|       final Result<int, String> x = Ok(2); | ||||
|       expect(x.unwrap<int>(), 2); | ||||
|       expect(() => x.unwrap<String>(), throwsA(isException)); | ||||
|     }); | ||||
| 
 | ||||
|     test('unwrap() returns error on Err value', () { | ||||
|       const Result<int, String> x = Err('error'); | ||||
|       final Result<int, String> x = Err('error'); | ||||
|       expect(x.unwrap<String>(), 'error'); | ||||
|       expect(() => x.unwrap<int>(), throwsA(isException)); | ||||
|     }); | ||||
| 
 | ||||
|     test('unwrapAsync() returns value on Ok value', () async { | ||||
|       const Result<int, String> x = Ok(2); | ||||
|       final Result<int, String> x = Ok(2); | ||||
|       expect(await x.unwrapAsync<int>(), 2); | ||||
|       expect(() async => x.unwrapAsync<String>(), throwsA(isException)); | ||||
|     }); | ||||
| 
 | ||||
|     test('unwrapAsync() returns error on Err value', () async { | ||||
|       const Result<int, String> x = Err('error'); | ||||
|       final Result<int, String> x = Err('error'); | ||||
|       expect(await x.unwrapAsync<String>(), 'error'); | ||||
|       expect(() async => x.unwrapAsync<int>(), throwsA(isException)); | ||||
|     }); | ||||
| 
 | ||||
|     test('fold() returns right value', () { | ||||
|       expect( | ||||
|         const Ok<String, String>('') | ||||
|             .fold<bool>((left) => true, (right) => false), | ||||
|         Ok<String, String>('').fold<bool>((left) => true, (right) => false), | ||||
|         true, | ||||
|       ); | ||||
|       expect( | ||||
|         const Err<String, String>('') | ||||
|             .fold<bool>((left) => true, (right) => false), | ||||
|         Err<String, String>('').fold<bool>((left) => true, (right) => false), | ||||
|         false, | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('foldAsync() returns right value', () async { | ||||
|       expect( | ||||
|         await const Ok<String, String>('').foldAsync<bool>( | ||||
|         await Ok<String, String>('').foldAsync<bool>( | ||||
|           (left) => Future.value(true), | ||||
|           (right) => Future.value(false), | ||||
|         ), | ||||
|         true, | ||||
|       ); | ||||
|       expect( | ||||
|         await const Err<String, String>('').foldAsync<bool>( | ||||
|         await Err<String, String>('').foldAsync<bool>( | ||||
|           (left) => Future.value(true), | ||||
|           (right) => Future.value(false), | ||||
|         ), | ||||
| @ -108,7 +106,7 @@ void main() { | ||||
|     }); | ||||
| 
 | ||||
|     test('swap() swaps values', () { | ||||
|       const Result<int, int> x = Ok(10); | ||||
|       final Result<int, int> x = Ok(10); | ||||
|       expect(x.isOk, true); | ||||
|       expect(x.isErr, false); | ||||
|       expect(x.ok, 10); | ||||
| @ -122,24 +120,24 @@ void main() { | ||||
|       'and() returns res if the result is `Ok`, otherwise ' | ||||
|       'returns the `Err` value of this.', | ||||
|       () { | ||||
|         const Result<int, String> x1 = Ok(2); | ||||
|         const Result<int, String> y1 = Err('late error'); | ||||
|         final Result<int, String> x1 = Ok(2); | ||||
|         final Result<int, String> y1 = Err('late error'); | ||||
|         expect(x1.and(y1), y1); | ||||
| 
 | ||||
|         const Result<String, String> x2 = Err('early error'); | ||||
|         const Result<String, String> y2 = Ok('foo'); | ||||
|         final Result<String, String> x2 = Err('early error'); | ||||
|         final Result<String, String> y2 = Ok('foo'); | ||||
|         expect(x2.and(y2), x2); | ||||
| 
 | ||||
|         const Result<void, String> x3 = Err('not a 2'); | ||||
|         const Result<void, String> y3 = Err('late error'); | ||||
|         final Result<void, String> x3 = Err('not a 2'); | ||||
|         final Result<void, String> y3 = Err('late error'); | ||||
|         expect(x3.and(y3), x3); | ||||
| 
 | ||||
|         const Result<dynamic, void> x4 = Ok(2); | ||||
|         const Result<dynamic, void> y4 = Ok('different result type'); | ||||
|         final Result<dynamic, void> x4 = Ok(2); | ||||
|         final Result<dynamic, void> y4 = Ok('different result type'); | ||||
|         expect(x4.and(y4), y4); | ||||
| 
 | ||||
|         const Result<int, void> x5 = Ok(2); | ||||
|         const Result<int, void> y5 = Ok(5); | ||||
|         final Result<int, void> x5 = Ok(2); | ||||
|         final Result<int, void> y5 = Ok(5); | ||||
|         expect(x5.and(y5), y5); | ||||
|       }, | ||||
|     ); | ||||
| @ -148,24 +146,24 @@ void main() { | ||||
|       'or() returns res if the result is `Err`, otherwise ' | ||||
|       'returns the `Ok` value of this.', | ||||
|       () { | ||||
|         const Result<int, String> x1 = Ok(2); | ||||
|         const Result<int, String> y1 = Err('late error'); | ||||
|         final Result<int, String> x1 = Ok(2); | ||||
|         final Result<int, String> y1 = Err('late error'); | ||||
|         expect(x1.or(y1), x1); | ||||
| 
 | ||||
|         const Result<String, String> x2 = Err('early error'); | ||||
|         const Result<String, String> y2 = Ok('foo'); | ||||
|         final Result<String, String> x2 = Err('early error'); | ||||
|         final Result<String, String> y2 = Ok('foo'); | ||||
|         expect(x2.or(y2), y2); | ||||
| 
 | ||||
|         const Result<void, String> x3 = Err('not a 2'); | ||||
|         const Result<void, String> y3 = Err('late error'); | ||||
|         final Result<void, String> x3 = Err('not a 2'); | ||||
|         final Result<void, String> y3 = Err('late error'); | ||||
|         expect(x3.or(y3), y3); | ||||
| 
 | ||||
|         const Result<dynamic, void> x4 = Ok(2); | ||||
|         const Result<dynamic, void> y4 = Ok('different result type'); | ||||
|         final Result<dynamic, void> x4 = Ok(2); | ||||
|         final Result<dynamic, void> y4 = Ok('different result type'); | ||||
|         expect(x4.or(y4), x4); | ||||
| 
 | ||||
|         const Result<int, void> x5 = Ok(2); | ||||
|         const Result<int, void> y5 = Ok(5); | ||||
|         final Result<int, void> x5 = Ok(2); | ||||
|         final Result<int, void> y5 = Ok(5); | ||||
|         expect(x5.or(y5), x5); | ||||
|       }, | ||||
|     ); | ||||
| @ -174,10 +172,10 @@ void main() { | ||||
|       'contains() returns true if the result is an Ok value ' | ||||
|       'containing the given value.', | ||||
|       () { | ||||
|         const Result<int, void> x1 = Ok(2); | ||||
|         final Result<int, void> x1 = Ok(2); | ||||
|         expect(x1.contains(2), true); | ||||
|         expect(x1.contains(3), false); | ||||
|         const Result<void, String> x2 = Err('Some error message'); | ||||
|         final Result<void, String> x2 = Err('Some error message'); | ||||
|         expect(x2.contains(2), false); | ||||
|       }, | ||||
|     ); | ||||
| @ -186,10 +184,10 @@ void main() { | ||||
|       'expect() return value if the result is an Ok value ' | ||||
|       'else throw Exception', | ||||
|       () { | ||||
|         const Result<int, String> x1 = Ok(2); | ||||
|         final Result<int, String> x1 = Ok(2); | ||||
|         expect(x1.expect('Testing expect'), 2); | ||||
| 
 | ||||
|         const Result<int, String> x2 = Err('emergency failure'); | ||||
|         final Result<int, String> x2 = Err('emergency failure'); | ||||
|         expect( | ||||
|           () => x2.expect('Testing expect'), | ||||
|           throwsA( | ||||
| @ -205,10 +203,10 @@ void main() { | ||||
|       'expectErr() return value if the result is an Err value ' | ||||
|       'else throw Exception', | ||||
|       () { | ||||
|         const Result<String, int> x1 = Err(2); | ||||
|         final Result<String, int> x1 = Err(2); | ||||
|         expect(x1.expectErr('Testing expect err'), 2); | ||||
| 
 | ||||
|         const Result<String, int> x2 = Ok('success value'); | ||||
|         final Result<String, int> x2 = Ok('success value'); | ||||
|         expect( | ||||
|           () => x2.expectErr('Testing expect err'), | ||||
|           throwsA( | ||||
| @ -223,12 +221,12 @@ void main() { | ||||
|     test( | ||||
|       'map() transforms Ok value.', | ||||
|       () { | ||||
|         const Result<bool, void> x1 = Ok(true); | ||||
|         final Result<bool, void> x1 = Ok(true); | ||||
| 
 | ||||
|         expect(x1.ok, true); | ||||
|         expect(x1.map((value) => false).ok, false); | ||||
| 
 | ||||
|         const Result<bool, String> x2 = Err('oops'); | ||||
|         final Result<bool, String> x2 = Err('oops'); | ||||
| 
 | ||||
|         expect(x2.map((value) => false).isErr, true); | ||||
|       }, | ||||
| @ -237,11 +235,11 @@ void main() { | ||||
|     test( | ||||
|       'mapErr() transforms Err value.', | ||||
|       () { | ||||
|         const Result<bool, String> x1 = Ok(true); | ||||
|         final Result<bool, String> x1 = Ok(true); | ||||
| 
 | ||||
|         expect(x1.mapErr((value) => false).isOk, true); | ||||
| 
 | ||||
|         const Result<bool, String> x2 = Err('oops'); | ||||
|         final Result<bool, String> x2 = Err('oops'); | ||||
| 
 | ||||
|         expect(x2.err, 'oops'); | ||||
|         expect(x2.mapErr((error) => 'failure').err, 'failure'); | ||||
| @ -251,12 +249,12 @@ void main() { | ||||
|     test( | ||||
|       'mapAsync() transforms Ok value.', | ||||
|       () async { | ||||
|         const Result<bool, void> x1 = Ok(true); | ||||
|         final Result<bool, void> x1 = Ok(true); | ||||
| 
 | ||||
|         expect(x1.ok, true); | ||||
|         expect((await x1.mapAsync((value) => Future.value(false))).ok, false); | ||||
| 
 | ||||
|         const Result<bool, String> x2 = Err('oops'); | ||||
|         final Result<bool, String> x2 = Err('oops'); | ||||
| 
 | ||||
|         expect((await x2.mapAsync((value) => Future.value(false))).isErr, true); | ||||
|       }, | ||||
| @ -265,14 +263,14 @@ void main() { | ||||
|     test( | ||||
|       'mapErrAsync() transforms Err value.', | ||||
|       () async { | ||||
|         const Result<bool, String> x1 = Ok(true); | ||||
|         final Result<bool, String> x1 = Ok(true); | ||||
| 
 | ||||
|         expect( | ||||
|           (await x1.mapErrAsync((value) => Future.value(false))).isOk, | ||||
|           true, | ||||
|         ); | ||||
| 
 | ||||
|         const Result<bool, String> x2 = Err('oops'); | ||||
|         final Result<bool, String> x2 = Err('oops'); | ||||
| 
 | ||||
|         expect(x2.err, 'oops'); | ||||
|         expect( | ||||
| @ -285,14 +283,14 @@ void main() { | ||||
|     test( | ||||
|       'either() transforms values.', | ||||
|       () { | ||||
|         const Result<bool, bool> x1 = Ok(true); | ||||
|         final Result<bool, bool> x1 = Ok(true); | ||||
|         final Result<int, String> y1 = | ||||
|             x1.either<int, String>((value) => 1, (error) => 'error'); | ||||
| 
 | ||||
|         expect(y1.isOk, true); | ||||
|         expect(y1.ok, 1); | ||||
| 
 | ||||
|         const Result<bool, bool> x2 = Err(true); | ||||
|         final Result<bool, bool> x2 = Err(true); | ||||
|         final Result<int, String> y2 = | ||||
|             x2.either<int, String>((value) => 1, (error) => 'error'); | ||||
| 
 | ||||
| @ -304,7 +302,7 @@ void main() { | ||||
|     test( | ||||
|       'eitherAsync() transforms values.', | ||||
|       () async { | ||||
|         const Result<bool, bool> x1 = Ok(true); | ||||
|         final Result<bool, bool> x1 = Ok(true); | ||||
|         final Result<int, String> y1 = await x1.eitherAsync<int, String>( | ||||
|           (value) => Future.value(1), | ||||
|           (error) => Future.value('error'), | ||||
| @ -313,7 +311,7 @@ void main() { | ||||
|         expect(y1.isOk, true); | ||||
|         expect(y1.ok, 1); | ||||
| 
 | ||||
|         const Result<bool, bool> x2 = Err(true); | ||||
|         final Result<bool, bool> x2 = Err(true); | ||||
|         final Result<int, String> y2 = await x2.eitherAsync<int, String>( | ||||
|           (value) => Future.value(1), | ||||
|           (error) => Future.value('error'), | ||||
| @ -370,9 +368,9 @@ void main() { | ||||
|       'conditional() returns Result on true test', | ||||
|       () { | ||||
|         final Result<int, String> x1 = Result.conditional<int, String>( | ||||
|           false, | ||||
|           2, | ||||
|           'error', | ||||
|           test: false, | ||||
|         ); | ||||
|         expect( | ||||
|           x1.isErr, | ||||
| @ -382,9 +380,9 @@ void main() { | ||||
|         expect(x1.err, 'error'); | ||||
| 
 | ||||
|         final Result<int, String> x2 = Result.conditional<int, String>( | ||||
|           true, | ||||
|           2, | ||||
|           'error', | ||||
|           test: true, | ||||
|         ); | ||||
|         expect( | ||||
|           x2.isOk, | ||||
| @ -399,9 +397,9 @@ void main() { | ||||
|       'conditionalLazy() returns Result on true test', | ||||
|       () { | ||||
|         final Result<int, String> x1 = Result.conditionalLazy<int, String>( | ||||
|           false, | ||||
|           () => 2, | ||||
|           () => 'error', | ||||
|           () => false, | ||||
|         ); | ||||
|         expect( | ||||
|           x1.isErr, | ||||
| @ -411,9 +409,9 @@ void main() { | ||||
|         expect(x1.err, 'error'); | ||||
| 
 | ||||
|         final Result<int, String> x2 = Result.conditionalLazy<int, String>( | ||||
|           true, | ||||
|           () => 2, | ||||
|           () => 'error', | ||||
|           () => true, | ||||
|         ); | ||||
|         expect( | ||||
|           x2.isOk, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user