# Path: natsort/compat/fake_fastnumbers.py
# def fast_float(
#     x: str,
#     key: Callable[[str], StrOrFloat] = lambda x: x,
#     nan: Optional[StrOrFloat] = None,
#     _uni: Callable[[str, StrOrFloat], StrOrFloat] = unicodedata.numeric,
#     _nan_inf: FrozenSet[str] = NAN_INF,
#     _first_char: FrozenSet[str] = POTENTIAL_FIRST_CHAR,
# ) -> StrOrFloat:
#     """
#     Convert a string to a float quickly, return input as-is if not possible.
# 
#     We don't need to accept all input that the real fast_int accepts because
#     natsort is controlling what is passed to this function.
# 
#     Parameters
#     ----------
#     x : str
#         String to attempt to convert to a float.
#     key : callable
#         Single-argument function to apply to *x* if conversion fails.
#     nan : object
#         Value to return instead of NaN if NaN would be returned.
# 
#     Returns
#     -------
#     *str* or *float*
# 
#     """
#     if x[0] in _first_char or x.lstrip()[:3] in _nan_inf:
#         try:
#             ret = float(x)
#             return nan if nan is not None and ret != ret else ret
#         except ValueError:
#             try:
#                 return _uni(x, key(x)) if len(x) == 1 else key(x)
#             except TypeError:  # pragma: no cover
#                 return key(x)
#     else:
#         try:
#             return _uni(x, key(x)) if len(x) == 1 else key(x)
#         except TypeError:  # pragma: no cover
#             return key(x)
# 
# def fast_int(
#     x: str,
#     key: Callable[[str], StrOrInt] = lambda x: x,
#     _uni: Callable[[str, StrOrInt], StrOrInt] = unicodedata.digit,
#     _first_char: FrozenSet[str] = POTENTIAL_FIRST_CHAR,
# ) -> StrOrInt:
#     """
#     Convert a string to a int quickly, return input as-is if not possible.
# 
#     We don't need to accept all input that the real fast_int accepts because
#     natsort is controlling what is passed to this function.
# 
#     Parameters
#     ----------
#     x : str
#         String to attempt to convert to an int.
#     key : callable
#         Single-argument function to apply to *x* if conversion fails.
# 
#     Returns
#     -------
#     *str* or *int*
# 
#     """
#     if x[0] in _first_char:
#         try:
#             return int(x)
#         except ValueError:
#             try:
#                 return _uni(x, key(x)) if len(x) == 1 else key(x)
#             except TypeError:  # pragma: no cover
#                 return key(x)
#     else:
#         try:
#             return _uni(x, key(x)) if len(x) == 1 else key(x)
#         except TypeError:  # pragma: no cover
#             return key(x)


import unicodedata
from math import isnan
from typing import Union, cast
from hypothesis import given
from hypothesis.strategies import floats, integers, text
from natsort.compat.fake_fastnumbers import fast_float, fast_int

def test_fast_int_leaves_float_string_as_is_example() -> None:
    assert fast_int("45.8") == "45.8"
    assert fast_int("nan") == "nan"
    assert fast_int("inf") == "inf"


@given(floats().filter(not_an_int))
def test_fast_int_leaves_float_string_as_is(x: float) -> None:
    assert fast_int(repr(x)) == repr(x)


def test_fast_int_converts_int_string_to_int_example() -> None:
    assert fast_int("-45") == -45
    assert fast_int("+45") == 45
    assert fast_int("۱۲") == 12
    assert fast_int("-۱۲") == -12


@given(integers())
def test_fast_int_converts_int_string_to_int(x: int) -> None:
    assert fast_int(repr(x)) == x


def test_fast_int_leaves_string_as_is_example() -> None:
    assert fast_int("invalid") == "invalid"


@given(text().filter(not_an_int).filter(bool))
def test_fast_int_leaves_string_as_is(x: str) -> None:

# Path: natsort/compat/fake_fastnumbers.py
# def fast_float(
#     x: str,
#     key: Callable[[str], StrOrFloat] = lambda x: x,
#     nan: Optional[StrOrFloat] = None,
#     _uni: Callable[[str, StrOrFloat], StrOrFloat] = unicodedata.numeric,
#     _nan_inf: FrozenSet[str] = NAN_INF,
#     _first_char: FrozenSet[str] = POTENTIAL_FIRST_CHAR,
# ) -> StrOrFloat:
#     """
#     Convert a string to a float quickly, return input as-is if not possible.
# 
#     We don't need to accept all input that the real fast_int accepts because
#     natsort is controlling what is passed to this function.
# 
#     Parameters
#     ----------
#     x : str
#         String to attempt to convert to a float.
#     key : callable
#         Single-argument function to apply to *x* if conversion fails.
#     nan : object
#         Value to return instead of NaN if NaN would be returned.
# 
#     Returns
#     -------
#     *str* or *float*
# 
#     """
#     if x[0] in _first_char or x.lstrip()[:3] in _nan_inf:
#         try:
#             ret = float(x)
#             return nan if nan is not None and ret != ret else ret
#         except ValueError:
#             try:
#                 return _uni(x, key(x)) if len(x) == 1 else key(x)
#             except TypeError:  # pragma: no cover
#                 return key(x)
#     else:
#         try:
#             return _uni(x, key(x)) if len(x) == 1 else key(x)
#         except TypeError:  # pragma: no cover
#             return key(x)
# 
# def fast_int(
#     x: str,
#     key: Callable[[str], StrOrInt] = lambda x: x,
#     _uni: Callable[[str, StrOrInt], StrOrInt] = unicodedata.digit,
#     _first_char: FrozenSet[str] = POTENTIAL_FIRST_CHAR,
# ) -> StrOrInt:
#     """
#     Convert a string to a int quickly, return input as-is if not possible.
# 
#     We don't need to accept all input that the real fast_int accepts because
#     natsort is controlling what is passed to this function.
# 
#     Parameters
#     ----------
#     x : str
#         String to attempt to convert to an int.
#     key : callable
#         Single-argument function to apply to *x* if conversion fails.
# 
#     Returns
#     -------
#     *str* or *int*
# 
#     """
#     if x[0] in _first_char:
#         try:
#             return int(x)
#         except ValueError:
#             try:
#                 return _uni(x, key(x)) if len(x) == 1 else key(x)
#             except TypeError:  # pragma: no cover
#                 return key(x)
#     else:
#         try:
#             return _uni(x, key(x)) if len(x) == 1 else key(x)
#         except TypeError:  # pragma: no cover
#             return key(x)


# Path: tests/test_fake_fastnumbers.py
import unicodedata
from math import isnan
from typing import Union, cast
from hypothesis import given
from hypothesis.strategies import floats, integers, text
from natsort.compat.fake_fastnumbers import fast_float, fast_int


def test_fast_int_leaves_float_string_as_is_example() -> None:
    assert fast_int("45.8") == "45.8"
    assert fast_int("nan") == "nan"
    assert fast_int("inf") == "inf"


@given(floats().filter(not_an_int))
def test_fast_int_leaves_float_string_as_is(x: float) -> None:
    assert fast_int(repr(x)) == repr(x)


def test_fast_int_converts_int_string_to_int_example() -> None:
    assert fast_int("-45") == -45
    assert fast_int("+45") == 45
    assert fast_int("۱۲") == 12
    assert fast_int("-۱۲") == -12


@given(integers())
def test_fast_int_converts_int_string_to_int(x: int) -> None:
    assert fast_int(repr(x)) == x


def test_fast_int_leaves_string_as_is_example() -> None:
    assert fast_int("invalid") == "invalid"


@given(text().filter(not_an_int).filter(bool))
def test_fast_int_leaves_string_as_is(x: str) -> None:

    assert fast_int(x) == x