use yog_mirror::host::{ALL, HostMirror};
pub(super) const CLASS: &str = "YogMirrors";
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
}
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
}
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
)
}
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>()
)
}