// Autogenerated from https://www.unicode.org/Public/latest/ucd/

const std = @import("std");
const unicode = std.unicode;

const CodePointIterator = @import("../segmenter/CodePoint.zig").CodePointIterator;

/// `caseFoldStr` will caseFold the code points in str, producing a slice of u8 with the new bytes.
/// Caller must free returned bytes with `allocator`.
pub fn caseFoldStr(allocator: std.mem.Allocator, str: []const u8) ![]u8 {
    var result = std.ArrayList(u8).init(allocator);
    defer result.deinit();
    var code_points = std.ArrayList(u21).init(allocator);
    defer code_points.deinit();

    // Gather decomposed code points.
    var iter = CodePointIterator{ .bytes = str };
    while (iter.next()) |cp| {
        for (toCaseFold(cp.code)) |fcp| {
            if (fcp == 0) break;
            try code_points.append(fcp);
        }
    }

    // Encode as UTF-8 code units.
    var buf: [4]u8 = undefined;
    for (code_points.items) |dcp| {
        const len = try unicode.utf8Encode(dcp, &buf);
        try result.appendSlice(buf[0..len]);
    }

    return try result.toOwnedSlice();
}

/// `toCaseFold` will convert a code point into its case folded equivalent. Note that this can result
/// in a mapping to more than one code point, known as the full case fold. An element with value zero (0)
/// in the returned 3 element array marks the end of the mapping sequence.
pub fn toCaseFold(cp: u21) [3]u21 {
    const slice: []const u21 = switch (cp) {
