<!--
 * 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/>.
-->



# Dart - Wyatt Type Utils

<p align="left">
  <a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
    <img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
  </a>
  <img src="https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square" alt="SDK: Dart & Flutter" />
</p>

Type Utils for Dart & Flutter.

## Option\<T>

**Option** is a container object which may or may not contain a non-null value. If a **Value** is present, `isPresent()` will return true and `get()` will return the value. Additional methods that depend on the presence or absence of a contained value are provided, such as `orElse()` (return a default value if value not present) and `ifPresent()` (execute a block of code if the value is present).

```dart
final Option<int> rand = Option.ofNullable(
  Random().nextBool() ? null : 10,
);

print(
  "`rand` is${rand.isNull ? "" : " not"} null, "
  "so it's value is ${rand.orElse(15)}",
);

// Ok, `orElse` is equivalent to ?? but the Option is 
// useful for match pattern and other utils accesses.
rand.match((value) {
    print('Value is: $value');
  }, () {
    print('Rand is null');
  },
);

print('`rand` contains 10 ? => ${rand.contains(10)}');
```

## Result\<T, E>

**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. 

```dart
Future<Result<TodoModel, AppError>> requestTodo() async => Result.tryCatchAsync(
  () => get('https://jsonplaceholder.typicode.com/todos/1'),
  (error) => ServerError('Error while getting todo'),
);

final Result<TodoModel, AppError> todo1 = await requestTodo();
// In Flutter:
todo1.either(buildWidgetWithTodo, buildSizedBox);
```

## Pair\<L, R>

**Pair** is a simple object which contains pair of two values.

```dart
const Pair<int, int> myPair = Pair(42, 16);
print(myPair.left); // prints '42'
print(myPair.right); // prints '16'
print(myPair); // prints '(42, 16)'
final List<int> myList = myPair.toList();
print(myList); // prints '[42, 16]'
```

## Extensions

This package also provides extensions for Dart types.

- Object
  - isNull
  - isNotNull
  - log
- Iterable
  - isNullOrEmpty
  - isNotNullOrEmpty
  - For bytes iterables
    - toTypedList
    - toStr
- String
  - isNullOrEmpty
  - isNotNullOrEmpty
  - toBytes

String 🔁 Uint8List works with encoding:

```dart
const String myString = 'abc';
final Uint8List bytes = myString.toBytes(from : Encoding.utf16);
print(bytes.toStr(to : Encoding.utf16)); // prints 'abc'
```

- DateTime
  - fromSecondsSinceEpoch
  - secondsSinceEpoch
  - timestamp
  - tomorrow
  - yesterday
  - today
  - add/sub/set
  - nextDay
  - previousDay
  - nextMonth
  - previousMonth
  - nextYear
  - previousYear
  - nextWeek
  - previousWeek
  - isFuture
  - isPast
  - isLeapYear
  - format
  - operators

The date formatter works with `String` formatter:

```dart
final DateTime date = DateTime(1999, 6, 30);
print(date.format([dd, '/', mm, '/', yy])); // prints '30/06/99'
```
