use yog_data::{Schema, Value};
use yog_ids as ids;
actions! {
Resolve { class: String, name: String, desc: String } -> Option<u32> = ids::service_nanite::RESOLVE, "nanite.YogReflect.resolve";
Call { member: u32, target: Value, args: Vec<Value> } -> Option<Value> = ids::service_nanite::CALL, "nanite.YogReflect.call";
Get { member: u32, target: Value } -> Option<Value> = ids::service_nanite::GET, "nanite.YogReflect.get";
Set { member: u32, target: Value, value: Value } -> bool = ids::service_nanite::SET, "nanite.YogReflect.set";
Release { objects: Vec<u64> } -> bool = ids::service_nanite::RELEASE, "nanite.YogReflect.release";
}
#[derive(Schema, Debug, Clone, Default, PartialEq, Eq)]
pub struct Mappings {
pub runtime: String,
pub classes: Vec<ClassMap>,
}
#[derive(Schema, Debug, Clone, Default, PartialEq, Eq)]
pub struct ClassMap {
pub named: String,
pub runtime: String,
pub fields: Vec<MemberMap>,
pub methods: Vec<MemberMap>,
}
#[derive(Schema, Debug, Clone, Default, PartialEq, Eq)]
pub struct MemberMap {
pub named: String,
pub desc: String,
pub runtime: String,
}
impl Mappings {
pub fn prune(&mut self) {
for c in &mut self.classes {
c.fields.retain(|m| m.named != m.runtime);
c.methods.retain(|m| m.named != m.runtime);
}
self.classes
.retain(|c| c.named != c.runtime || !c.fields.is_empty() || !c.methods.is_empty());
self.classes.sort_by(|a, b| a.named.cmp(&b.named));
}
}
#[derive(Schema, Debug, Clone, Default, PartialEq, Eq)]
pub struct Inject {
pub point: String,
pub kind: String,
pub class: String,
pub method: String,
pub desc: String,
pub at: String,
pub target: String,
pub ordinal: i32,
pub shift: String,
pub cancellable: bool,
pub index: i32,
pub constant: String,
pub value_desc: String,
pub write: bool,
pub locals: Vec<String>,
}
pub fn point(i: &Inject) -> String {
use ids::nanite_point::{AT, MEMBER, TARGET};
let mut key = format!(
"{}{TARGET}{}{MEMBER}{}{}{AT}{}",
i.kind, i.class, i.method, i.desc, i.at
);
for part in [i.target.clone(), qualifier(i)] {
if !part.is_empty() {
key.push_str(TARGET);
key.push_str(&part);
}
}
key
}
fn qualifier(i: &Inject) -> String {
match i.kind.as_str() {
ids::nanite_kind::MODIFY_ARG => i.index.to_string(),
ids::nanite_kind::MODIFY_VARIABLE => format!("{}{}", i.index, i.value_desc),
ids::nanite_kind::MODIFY_CONSTANT => i.constant.clone(),
ids::nanite_kind::REDIRECT if i.write => ids::nanite_point::WRITE.to_owned(),
ids::nanite_kind::INJECT => i.locals.join(ids::nanite_local::LIST),
_ => String::new(),
}
}
#[derive(Schema, Debug, Clone, Default, PartialEq, Eq)]
pub struct Nanites {
pub injects: Vec<Inject>,
}
#[derive(Schema, Debug, Clone, Default, PartialEq)]
pub struct Injected {
pub point: String,
pub this: Value,
pub args: Vec<Value>,
pub value: Value,
pub cancelled: bool,
pub returned: bool,
pub locals: Vec<Value>,
pub original: Value,
}