cluna 1.1.0

Tool to convert Lua code into Clue code Made by MarkosTh09
Documentation
---
source: src/main.rs
expression: compiled
input_file: test-data/lua5.4-tests/utf8.lua
---
print("testing UTF-8 library");
local utf8 = require('utf8')
local fn checkerror(msg, f, ...) {
    local s, err = pcall(f, ...)
    assert(!s && string.find(err, msg));
}
local fn len(s) {
    return #string.gsub(s, "[\x80-\xBF]", "")
}
local justone = "^" .. utf8.charpattern .. "$"
local fn checksyntax(s, t) {
    local ts = {
        "return '"
    }
    for i = 1, #t {
        ts[(i + 1)] = string.format("\\u{%x}", t[(i)])
    }
    ts[(#t + 2)] = "'"
    ts = table.concat(ts)
    assert(assert(load(ts))() == s);
}
assert(!utf8.offset("alo", 5));
assert(!utf8.offset("alo", -4));
local fn check(s, t, nonstrict) {
    local l = utf8.len(s, 1, -1, nonstrict)
    assert(#t == l && len(s) == l);
    assert(utf8.char(table.unpack(t)) == s);
    assert(utf8.offset(s, 0) == 1);
    checksyntax(s, t);
    local t1 = {
        utf8.codepoint(s, 1, -1, nonstrict)
    }
    assert(#t == #t1);
    for i = 1, #t {
        assert(t[(i)] == t1[(i)]);
    }
    for i = 1, l {
        local pi = utf8.offset(s, i)
        local pi1 = utf8.offset(s, 2, pi)
        assert(string.find(string.sub(s, pi, pi1 - 1), justone));
        assert(utf8.offset(s, -1, pi1) == pi);
        assert(utf8.offset(s, i - l - 1) == pi);
        assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi, pi, nonstrict)));
        for j = pi, pi1 - 1 {
            assert(utf8.offset(s, 0, j) == pi);
        }
        for j = pi + 1, pi1 - 1 {
            assert(!utf8.len(s, j));
        }
        assert(utf8.len(s, pi, pi, nonstrict) == 1);
        assert(utf8.len(s, pi, pi1 - 1, nonstrict) == 1);
        assert(utf8.len(s, pi, -1, nonstrict) == l - i + 1);
        assert(utf8.len(s, pi1, -1, nonstrict) == l - i);
        assert(utf8.len(s, 1, pi, nonstrict) == i);
    }
    local i = 0
    for p, c with utf8.codes(s, nonstrict) {
        i = i + 1
        assert(c == t[(i)] && p == utf8.offset(s, i));
        assert(utf8.codepoint(s, p, p, nonstrict) == c);
    }
    assert(i == #t);
    i = 0
    for c with string.gmatch(s, utf8.charpattern) {
        i = i + 1
        assert(c == utf8.char(t[(i)]));
    }
    assert(i == #t);
    for i = 1, l {
        assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1));
    }
}
{
    local fn check(s, p) {
        local a, b = utf8.len(s)
        assert(!a && b == p);
    }
    check("abc\xE3def", 4);
    check("汉字\x80", #("汉字") + 1);
    check("\xF4\x9F\xBF", 1);
    check("\xF4\x9F\xBF\xBF", 1);
}
{
    local fn errorcodes(s) {
        checkerror("invalid UTF%-8 code", fn () {
            for c with utf8.codes(s) {
                assert(c);
            }
        });
    }
    errorcodes("ab\xff");
    errorcodes("\u{110000}");
    local f = utf8.codes("")
    assert(f("", 2) == nil);
    assert(f("", -1) == nil);
    assert(f("", math.mininteger) == nil);
}
checkerror("position out of bounds", utf8.offset, "abc", 1, 5);
checkerror("position out of bounds", utf8.offset, "abc", 1, -4);
checkerror("position out of bounds", utf8.offset, "", 1, 2);
checkerror("position out of bounds", utf8.offset, "", 1, -1);
checkerror("continuation byte", utf8.offset, "𦧺", 1, 2);
checkerror("continuation byte", utf8.offset, "𦧺", 1, 2);
checkerror("continuation byte", utf8.offset, "\x80", 1);
checkerror("out of bounds", utf8.len, "abc", 0, 2);
checkerror("out of bounds", utf8.len, "abc", 1, 4);
local s = "hello World"
local t = {
    string.byte(s, 1, -1)
}
for i = 1, utf8.len(s) {
    assert(t[(i)] == string.byte(s, i));
}
check(s, t);
check("汉字/漢字", {
    27721, 
    23383, 
    47, 
    28450, 
    23383
});
{
    local s = "áéí\128"
    local t = {
        utf8.codepoint(s, 1, #s - 1)
    }
    assert(#t == 3 && t[(1)] == 225 && t[(2)] == 233 && t[(3)] == 237);
    checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s);
    checkerror("out of bounds", utf8.codepoint, s, #s + 1);
    t = {
        utf8.codepoint(s, 4, 3)
    }
    assert(#t == 0);
    checkerror("out of bounds", utf8.codepoint, s, -(#s + 1), 1);
    checkerror("out of bounds", utf8.codepoint, s, 1, #s + 1);
    assert(utf8.codepoint("\u{D7FF}") == 0xD800 - 1);
    assert(utf8.codepoint("\u{E000}") == 0xDFFF + 1);
    assert(utf8.codepoint("\u{D800}", 1, 1, true) == 0xD800);
    assert(utf8.codepoint("\u{DFFF}", 1, 1, true) == 0xDFFF);
    assert(utf8.codepoint("\u{7FFFFFFF}", 1, 1, true) == 0x7FFFFFFF);
}
assert(utf8.char() == "");
assert(utf8.char(0, 97, 98, 99, 1) == "\0abc\1");
assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF);
assert(utf8.codepoint(utf8.char(0x7FFFFFFF), 1, 1, true) == (1 << 31) - 1);
checkerror("value out of range", utf8.char, 0x7FFFFFFF + 1);
checkerror("value out of range", utf8.char, -1);
local fn invalid(s) {
    checkerror("invalid UTF%-8 code", utf8.codepoint, s);
    assert(!utf8.len(s));
}
invalid("\xF4\x9F\xBF\xBF");
invalid("\u{D800}");
invalid("\u{DFFF}");
invalid("\xC0\x80");
invalid("\xC1\xBF");
invalid("\xE0\x9F\xBF");
invalid("\xF0\x8F\xBF\xBF");
invalid("\x80");
invalid("\xBF");
invalid("\xFE");
invalid("\xFF");
check("", {});
s = "\0 \x7F\z
     \xC2\x80 \xDF\xBF\z
     \xE0\xA0\x80 \xEF\xBF\xBF\z
     \xF0\x90\x80\x80  \xF4\x8F\xBF\xBF"
s = string.gsub(s, " ", "")
check(s, {
    0, 
    0x7F, 
    0x80, 
    0x7FF, 
    0x800, 
    0xFFFF, 
    0x10000, 
    0x10FFFF
});
{
    local s = "\u{4000000}\u{7FFFFFFF}"
    assert(#s == 12);
    check(s, {
        0x4000000, 
        0x7FFFFFFF
    }, true);
    s = "\u{200000}\u{3FFFFFF}"
    assert(#s == 10);
    check(s, {
        0x200000, 
        0x3FFFFFF
    }, true);
    s = "\u{10000}\u{1fffff}"
    assert(#s == 8);
    check(s, {
        0x10000, 
        0x1FFFFF
    }, true);
}
x = "日本語a-4\0éó"
check(x, {
    26085, 
    26412, 
    35486, 
    97, 
    45, 
    52, 
    0, 
    233, 
    243
});
check("𣲷𠜎𠱓𡁻𠵼ab𠺢", {
    0x23CB7, 
    0x2070E, 
    0x20C53, 
    0x2107B, 
    0x20D7C, 
    0x61, 
    0x62, 
    0x20EA2
});
check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF", {
    0x28CCA, 
    0x29D98, 
    0x269FA, 
    0x28CD2, 
    0x2512B, 
    0x244D3, 
    0x10ffff
});
local i = 0
for p, c with string.gmatch(x, "()(" .. utf8.charpattern .. ")") {
    i = i + 1
    assert(utf8.offset(x, i) == p);
    assert(utf8.len(x, p) == utf8.len(x) - i + 1);
    assert(utf8.len(c) == 1);
    for j = 1, #c - 1 {
        assert(utf8.offset(x, 0, p + j - 1) == p);
    }
}
print('ok');