#include "foundation/parse.h"
#include "test_harness.h"

#include <cstdint>
#include <string_view>

using pp::foundation::parse_u32;
using pp::foundation::StatusCode;

namespace {

void accepts_decimal_uint32_values(pp::tests::Harness& h)
{
    const auto zero = parse_u32("0");
    const auto ordinary = parse_u32("12345");
    const auto max = parse_u32("4294967295");

    PP_EXPECT(h, zero.ok());
    PP_EXPECT(h, zero.value() == 0U);
    PP_EXPECT(h, ordinary.ok());
    PP_EXPECT(h, ordinary.value() == 12345U);
    PP_EXPECT(h, max.ok());
    PP_EXPECT(h, max.value() == UINT32_MAX);
}

void rejects_empty_signed_and_mixed_input(pp::tests::Harness& h)
{
    const auto empty = parse_u32("");
    const auto negative = parse_u32("-1");
    const auto positive = parse_u32("+1");
    const auto trailing = parse_u32("12px");
    const auto spaced = parse_u32(" 12");

    PP_EXPECT(h, !empty.ok());
    PP_EXPECT(h, empty.status().code == StatusCode::invalid_argument);
    PP_EXPECT(h, !negative.ok());
    PP_EXPECT(h, negative.status().code == StatusCode::invalid_argument);
    PP_EXPECT(h, !positive.ok());
    PP_EXPECT(h, positive.status().code == StatusCode::invalid_argument);
    PP_EXPECT(h, !trailing.ok());
    PP_EXPECT(h, trailing.status().code == StatusCode::invalid_argument);
    PP_EXPECT(h, !spaced.ok());
    PP_EXPECT(h, spaced.status().code == StatusCode::invalid_argument);
}

void rejects_overflow_without_wrapping(pp::tests::Harness& h)
{
    const auto overflow = parse_u32("4294967296");
    const auto very_large = parse_u32("999999999999999999999999999999999999");

    PP_EXPECT(h, !overflow.ok());
    PP_EXPECT(h, overflow.status().code == StatusCode::out_of_range);
    PP_EXPECT(h, !very_large.ok());
    PP_EXPECT(h, very_large.status().code == StatusCode::out_of_range);
}

}

int main()
{
    pp::tests::Harness harness;
    harness.run("accepts_decimal_uint32_values", accepts_decimal_uint32_values);
    harness.run("rejects_empty_signed_and_mixed_input", rejects_empty_signed_and_mixed_input);
    harness.run("rejects_overflow_without_wrapping", rejects_overflow_without_wrapping);
    return harness.finish();
}
