BareGit
#include "username.h"

#include <string>

#include <uni_algo/case.h>
#include <uni_algo/conv.h>
#include <uni_algo/norm.h>
#include <uni_algo/prop.h>

mw::E<NormalizedUsername> normalizeUsername(const std::string& input)
{
    if(!una::is_valid_utf8(input))
    {
        return std::unexpected(mw::runtimeError("Invalid username"));
    }
    std::string username = una::norm::to_nfc_utf8(input);
    if(username.empty() || username.size() > 32)
    {
        return std::unexpected(mw::runtimeError("Invalid username"));
    }

    const std::u32string codepoints = una::utf8to32u(username);
    for(char32_t codepoint : codepoints)
    {
        if(una::codepoint::prop(codepoint).General_Category_Cc())
        {
            return std::unexpected(mw::runtimeError("Invalid username"));
        }
    }
    if(una::codepoint::prop(codepoints.front()).White_Space() ||
       una::codepoint::prop(codepoints.back()).White_Space())
    {
        return std::unexpected(mw::runtimeError("Invalid username"));
    }

    std::string key = una::cases::to_casefold_utf8(username);
    key = una::norm::to_nfc_utf8(key);
    return NormalizedUsername{std::move(username), std::move(key)};
}