//! Autogenerated by GenerateDef from src/aro/Builtins/bpf.def, do not edit
// zig fmt: off

const std = @import("std");

pub fn with(comptime Properties: type) type {
return struct {

/// Integer starting at 0 derived from the unique index,
/// corresponds with the data array index.
pub const Tag = enum(u16) {    __builtin_btf_type_id,
    __builtin_preserve_enum_value,
    __builtin_preserve_field_info,
    __builtin_preserve_type_info,
};

pub fn fromName(name: []const u8) ?Properties {
    const data_index = tagFromName(name) orelse return null;
    return data[@intFromEnum(data_index)];
}

pub fn tagFromName(name: []const u8) ?Tag {
    const unique_index = uniqueIndex(name) orelse return null;
    return @enumFromInt(unique_index - 1);
}

pub fn fromTag(tag: Tag) Properties {
    return data[@intFromEnum(tag)];
}

pub fn nameFromTagIntoBuf(tag: Tag, name_buf: []u8) []u8 {
    std.debug.assert(name_buf.len >= longest_name);
    const unique_index = @intFromEnum(tag) + 1;
    return nameFromUniqueIndex(unique_index, name_buf);
}

pub fn nameFromTag(tag: Tag) NameBuf {
    var name_buf: NameBuf = undefined;
    const unique_index = @intFromEnum(tag) + 1;
    const name = nameFromUniqueIndex(unique_index, &name_buf.buf);
    name_buf.len = @intCast(name.len);
    return name_buf;
}

pub const NameBuf = struct {
    buf: [longest_name]u8 = undefined,
    len: std.math.IntFittingRange(0, longest_name),

    pub fn span(self: *const NameBuf) []const u8 {
        return self.buf[0..self.len];
    }
};

pub fn exists(name: []const u8) bool {
    if (name.len < shortest_name or name.len > longest_name) return false;

    var index: u16 = 0;
    for (name) |c| {
        index = findInList(dafsa[index].child_index, c) orelse return false;
    }
    return dafsa[index].end_of_word;
}

pub const shortest_name = 21;
pub const longest_name = 29;

/// Search siblings of `first_child_index` for the `char`
/// If found, returns the index of the node within the `dafsa` array.
/// Otherwise, returns `null`.
pub fn findInList(first_child_index: u16, char: u8) ?u16 {
    @setEvalBranchQuota(8);
    var index = first_child_index;
    while (true) {
        if (dafsa[index].char == char) return index;
        if (dafsa[index].end_of_list) return null;
        index += 1;
    }
    unreachable;
}

/// Returns a unique (minimal perfect hash) index (starting at 1) for the `name`,
/// or null if the name was not found.
pub fn uniqueIndex(name: []const u8) ?u16 {
    if (name.len < shortest_name or name.len > longest_name) return null;

    var index: u16 = 0;
    var node_index: u16 = 0;

    for (name) |c| {
        const child_index = findInList(dafsa[node_index].child_index, c) orelse return null;
        var sibling_index = dafsa[node_index].child_index;
        while (true) {
            const sibling_c = dafsa[sibling_index].char;
            std.debug.assert(sibling_c != 0);
            if (sibling_c < c) {
                index += dafsa[sibling_index].number;
            }
            if (dafsa[sibling_index].end_of_list) break;
            sibling_index += 1;
        }
        node_index = child_index;
        if (dafsa[node_index].end_of_word) index += 1;
    }

    if (!dafsa[node_index].end_of_word) return null;

    return index;
}

/// Returns a slice of `buf` with the name associated with the given `index`.
/// This function should only be called with an `index` that
/// is already known to exist within the `dafsa`, e.g. an index
/// returned from `uniqueIndex`.
pub fn nameFromUniqueIndex(index: u16, buf: []u8) []u8 {
    std.debug.assert(index >= 1 and index <= data.len);

    var node_index: u16 = 0;
    var count: u16 = index;
    var w = std.Io.Writer.fixed(buf);

    while (true) {
        var sibling_index = dafsa[node_index].child_index;
        while (true) {
            if (dafsa[sibling_index].number > 0 and dafsa[sibling_index].number < count) {
                count -= dafsa[sibling_index].number;
            } else {
                w.writeByte(dafsa[sibling_index].char) catch unreachable;
                node_index = sibling_index;
                if (dafsa[node_index].end_of_word) {
                    count -= 1;
                }
                break;
            }

            if (dafsa[sibling_index].end_of_list) break;
            sibling_index += 1;
        }
        if (count == 0) break;
    }

    return w.buffered();
}

const Node = packed struct {
    char: u8,
    /// Nodes are numbered with "an integer which gives the number of words that
    /// would be accepted by the automaton starting from that state." This numbering
    /// allows calculating "a one-to-one correspondence between the integers 1 to L
    /// (L is the number of words accepted by the automaton) and the words themselves."
    ///
    /// Essentially, this allows us to have a minimal perfect hashing scheme such that
    /// it's possible to store & lookup the properties of each builtin using a separate array.
    number: std.math.IntFittingRange(0, data.len),
    /// If true, this node is the end of a valid builtin.
    /// Note: This does not necessarily mean that this node does not have child nodes.
    end_of_word: bool,
    /// If true, this node is the end of a sibling list.
    /// If false, then (index + 1) will contain the next sibling.
    end_of_list: bool,
    /// Index of the first child of this node.
    child_index: u16,
};

const dafsa = [_]Node{
    .{ .char = 0, .end_of_word = false, .end_of_list = true, .number = 0, .child_index = 1 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 2 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 3 },
    .{ .char = 'b', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 4 },
    .{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 5 },
    .{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 6 },
    .{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 7 },
    .{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 8 },
    .{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 9 },
    .{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 10 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 4, .child_index = 11 },
    .{ .char = 'b', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 13 },
    .{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 14 },
    .{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 15 },
    .{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 16 },
    .{ .char = 'f', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 17 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 18 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 19 },
    .{ .char = 's', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 20 },
    .{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 21 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 22 },
    .{ .char = 'y', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 23 },
    .{ .char = 'r', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 24 },
    .{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 25 },
    .{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 26 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 27 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 28 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 29 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 3, .child_index = 30 },
    .{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 33 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 34 },
    .{ .char = 'f', .end_of_word = false, .end_of_list = false, .number = 1, .child_index = 35 },
    .{ .char = 't', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 36 },
    .{ .char = 'd', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
    .{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 37 },
    .{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 38 },
    .{ .char = 'y', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 39 },
    .{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 40 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 41 },
    .{ .char = 'p', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 42 },
    .{ .char = 'm', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 43 },
    .{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 44 },
    .{ .char = 'e', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 45 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 46 },
    .{ .char = 'd', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 45 },
    .{ .char = '_', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 47 },
    .{ .char = 'v', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 48 },
    .{ .char = 'i', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 49 },
    .{ .char = 'a', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 50 },
    .{ .char = 'n', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 51 },
    .{ .char = 'l', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 52 },
    .{ .char = 'f', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 53 },
    .{ .char = 'u', .end_of_word = false, .end_of_list = true, .number = 1, .child_index = 54 },
    .{ .char = 'o', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
    .{ .char = 'e', .end_of_word = true, .end_of_list = true, .number = 1, .child_index = 0 },
};
pub const data = blk: {
    @setEvalBranchQuota(36);
    break :blk [_]Properties{
        .{ .param_str = "LUi.", .attributes = .{ .custom_typecheck = true } },
        .{ .param_str = "Li.", .attributes = .{ .custom_typecheck = true } },
        .{ .param_str = "Ui.", .attributes = .{ .custom_typecheck = true } },
        .{ .param_str = "LUi.", .attributes = .{ .custom_typecheck = true } },
    };
};
};
}
