<commit_before># PolyCast

[![Build Status](https://travis-ci.org/theodorejb/PolyCast.svg?branch=master)](https://travis-ci.org/theodorejb/PolyCast) [![Packagist Version](https://img.shields.io/packagist/v/theodorejb/polycast.svg)](https://packagist.org/packages/theodorejb/polycast) [![License](https://img.shields.io/packagist/l/theodorejb/polycast.svg)](LICENSE.md)

Provides `int_castable`, `float_castable`, and `string_castable` functions.
The functions return true if a value can be cast to the designated type without
data loss, and false if it cannot.

Three complementary functions are also included: `to_int`, `to_float`, and
`to_string`. These functions cast and return a value if it can be converted
without data loss, and throw a `CastException` if it cannot.

This library was originally based on the [Safe Casting Functions RFC](https://wiki.php.net/rfc/safe_cast)
proposed (but ultimately rejected) for PHP 7.

## Acceptable casts

### `int_castable`

* Integers
* Floats without a remainder between `PHP_INT_MIN` and `PHP_INT_MAX`
* Strings with an optional positive/negative sign, without leading zeros, and
containing the digits 0-9 with a value between `PHP_INT_MIN` and `PHP_INT_MAX`.

### `float_castable`

* Floats
* Integers
* Strings with an optional positive/negative sign, without leading zeros, and
matching the format described at http://php.net/manual/en/language.types.float.php.

### `string_castable`

* Strings
* Integers
* Floats
* Objects with a `__toString` method

The functions will always return false if passed `null`, `true` or `false`,
an array, resource, or object (with the exception of objects with a `__toString`
method passed to `string_castable`).

## Installation

To install via [Composer](https://getcomposer.org/),
add the following to the composer.json file in your project root:

```json
{
    "require": {
        "theodorejb/polycast": "~0.7"
    }
}
```

Then run `composer install` and require `vendor/autoload.php`
in your application's bootstrap file.

## Usage examples

### Input validation

```php
function validatePriceBreakReq(array $data)
{
    if (!isset($data['quantity'], $data['price'])) {
        throw new Exception('quantity and price are required');
    } elseif (!int_castable($data['quantity'])) {
        throw new Exception('quantity must be an integer');
    } elseif (!float_castable($data['price'])) {
        throw new Exception('price must be a number');
    }
}

function addPriceBreak(int $itemId, int $quantity, float $price)
{
    // insert price break into database
}

// route handler
$app->post('/items/:id/pricebreaks/', function (int $id) use($app) {
    $data = $app->request->getBody();
    validatePriceBreakReq($data);
    addPriceBreak($id, (int) $data['quantity'], (float) $data['price']);
});
```

### Safe type conversion

```php
try {
    $totalRevenue = 0;
    $totalTransactions = 0;

    foreach ($csvRows as $row) {
        $totalRevenue += to_float($row['monthly_revenue']);<commit_msg>Minor readme improvements<commit_after># PolyCast

[![Build Status](https://travis-ci.org/theodorejb/PolyCast.svg?branch=master)](https://travis-ci.org/theodorejb/PolyCast) [![Packagist Version](https://img.shields.io/packagist/v/theodorejb/polycast.svg)](https://packagist.org/packages/theodorejb/polycast) [![License](https://img.shields.io/packagist/l/theodorejb/polycast.svg)](LICENSE.md)

Provides `int_castable`, `float_castable`, and `string_castable` functions.
The functions return true if a value can be cast to the designated type without
data loss, and false if it cannot.

Three complementary functions are also included: `to_int`, `to_float`, and
`to_string`. These functions cast and return a value if the corresponding
*_castable* function returns true, and throw a `CastException` if it returns false.

This library was originally based on the [Safe Casting Functions RFC](https://wiki.php.net/rfc/safe_cast)
proposed (but ultimately declined) for PHP 7.

## Acceptable casts

### `int_castable`

* Integers
* Floats without a remainder between `PHP_INT_MIN` and `PHP_INT_MAX`
* Strings with an optional positive/negative sign, without leading zeros, and
containing the digits 0-9 with a value between `PHP_INT_MIN` and `PHP_INT_MAX`.

### `float_castable`

* Floats
* Integers
* Strings with an optional positive/negative sign, without leading zeros, and
matching the format described at http://php.net/manual/en/language.types.float.php.

### `string_castable`

* Strings
* Integers
* Floats
* Objects with a `__toString` method

The functions will always return false if passed `null`, `true` or `false`,
an array, resource, or object (with the exception of objects with a `__toString`
method passed to `string_castable`).

## Installation

To install via [Composer](https://getcomposer.org/),
add the following to the composer.json file in your project root:

```json
{
    "require": {
        "theodorejb/polycast": "~0.7"
    }
}
```

Then run `composer install` and require `vendor/autoload.php`
in your application's bootstrap file.

## Usage examples

### Input validation

```php
function validatePriceBreakReq(array $data)
{
    if (!isset($data['quantity'], $data['price'])) {
        throw new Exception('quantity and price are required');
    } elseif (!int_castable($data['quantity'])) {
        throw new Exception('quantity must be an integer');
    } elseif (!float_castable($data['price'])) {
        throw new Exception('price must be a number');
    }
}

function addPriceBreak(int $itemId, int $quantity, float $price)
{
    // insert price break into database
}

// route handler
$app->post('/items/:id/pricebreaks/', function (int $id) use($app) {
    $data = $app->request->getBody();
    validatePriceBreakReq($data);
    addPriceBreak($id, (int)$data['quantity'], (float)$data['price']);
});
```

### Safe type conversion

```php
try {
    $totalRevenue = 0;
    $totalTransactions = 0;

    foreach ($csvRows as $row) {
        $totalRevenue += to_float($row['monthly_revenue']);
{'fraction_non_alphanumeric': 0.13390928725701945, 'fraction_numerical': 0.0023259677687323477, 'mean_word_length': 4.684608120868744, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 14, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '34637', 'n_tokens_mistral': 1913, 'n_tokens_neox': 1828, 'n_words': 572}