yog-event 0.11.1

Yog event system — pub/sub for game/server events.
Documentation
//! `YogMirrors`: the host's mirrors for the Java host that writes them —
//! each one's address, key space and field indices, from their one source
//! (`yog_mirror::host`).

use yog_mirror::host::{ALL, HostMirror};

/// The generated class.
pub(super) const CLASS: &str = "YogMirrors";

/// `yog:mirror/yog/entity` → `Entity`, `…/client/entity` → `ClientEntity`.
fn class_of(m: &HostMirror) -> String {
    let path = m
        .address
        .strip_prefix(yog_ids::host_mirror::PREFIX)
        .unwrap_or(m.address);
    path.split(yog_ids::sep::PATH)
        .map(super::class_name)
        .collect()
}

fn mirror(m: &HostMirror) -> String {
    let mut out = format!(
        "\n    /** {address} (`yog_mirror::host`). */\n    public static final class {class} {{\n        private {class}() {{}}\n\n        public static final String ADDRESS = \"{address}\";\n        public static final String SPACE = \"{space}\";\n",
        address = m.address,
        class = class_of(m),
        space = m.space,
    );
    for (i, f) in m.fields.iter().enumerate() {
        out.push_str(&format!(
            "        /** Field `{}` ({:?} × {}): its index, its bit is {{@code 1L << index}}. */\n        public static final int {} = {i};\n",
            f.name,
            f.kind,
            f.count,
            f.name.to_uppercase()
        ));
    }
    out.push_str("    }\n");
    out
}

/// `BlockTrait`: each of `yog_ids::block_trait`'s bit, its place in the list.
fn traits() -> String {
    let mut out = String::from(
        "\n    /** A block's traits (`yog_ids::block_trait`): each one's bit index. */\n    public static final class BlockTrait {\n        private BlockTrait() {}\n\n",
    );
    for (i, name) in yog_ids::block_trait::ALL_VALUES.iter().enumerate() {
        out.push_str(&format!(
            "        public static final int {} = {i};\n",
            name.to_uppercase()
        ));
    }
    out.push_str("    }\n");
    out
}

/// An atom field's "none" (`yog_mirror::cell::NO_ATOM`, as Java's int).
fn no_atom() -> String {
    format!(
        "\n    /** An atom field's \"none\" (`yog_mirror::NO_ATOM`): not 0, which is an atom. */\n    public static final int NO_ATOM = {};\n",
        yog_mirror::NO_ATOM as i32
    )
}

/// The class's text.
pub(super) fn file(package: &str) -> String {
    let body: String = no_atom() + &ALL.iter().map(|m| mirror(m)).collect::<String>() + &traits();
    format!(
        "{}package {package};\n\n/** The host's mirrors: their addresses, key spaces and fields. */\npublic final class {CLASS} {{\n    private {CLASS}() {{}}\n{body}}}\n",
        super::HEADER.comment::<yog_codegen_java::Java>()
    )
}