1use yog_event::nanite::{Inject, Injected, Nanites, point};
7use yog_sync::Mutex;
8
9use super::{Java, Member, Nanite};
10use crate::Registry;
11
12pub struct InjectEntry {
14 pub kind: &'static str,
16 pub member: &'static Member,
17 pub at: &'static str,
19 pub target: &'static str,
21 pub ordinal: i32,
22 pub shift: &'static str,
24 pub cancellable: bool,
25 pub priority: i32,
27 pub index: i32,
29 pub constant: &'static str,
31 pub value_desc: &'static str,
33 pub handler: Option<fn(&mut Hook)>,
35}
36
37impl InjectEntry {
38 pub fn spec(&self) -> Inject {
40 let (method, desc) = self.member.signature();
41 let class = self.member.class();
42 let mut spec = Inject {
43 point: String::new(),
44 kind: self.kind.to_owned(),
45 class: class.to_owned(),
46 method: method.to_owned(),
47 desc,
48 at: self.at.to_owned(),
49 target: self.target.to_owned(),
50 ordinal: self.ordinal,
51 shift: self.shift.to_owned(),
52 cancellable: self.cancellable,
53 index: self.index,
54 constant: self.constant.to_owned(),
55 value_desc: self.value_desc.to_owned(),
56 };
57 spec.point = point(&spec);
58 spec
59 }
60}
61
62const ORIGINAL_CLASS: &str = "java.util.function.Function";
64const ORIGINAL_METHOD: &str = "apply";
65
66fn original_desc() -> String {
67 let object = super::java::class_desc("java.lang.Object");
68 super::method_desc(std::slice::from_ref(&object), &object)
69}
70
71#[doc(hidden)]
73pub fn __yog_nanite_registry() -> &'static Mutex<Vec<InjectEntry>> {
74 static REG: Mutex<Vec<InjectEntry>> = Mutex::new(Vec::new());
75 ®
76}
77
78#[doc(hidden)]
81pub fn __declare(kind: &'static str, member: &'static Member, target: &'static str) {
82 __yog_nanite_registry().lock().push(InjectEntry {
83 kind,
84 member,
85 at: "",
86 target,
87 ordinal: -1,
88 shift: "",
89 cancellable: false,
90 priority: 0,
91 index: -1,
92 constant: "",
93 value_desc: "",
94 handler: None,
95 });
96}
97
98#[doc(hidden)]
100pub fn __yog_nanites() -> Vec<u8> {
101 let injects = __yog_nanite_registry()
102 .lock()
103 .iter()
104 .map(InjectEntry::spec)
105 .collect();
106 yog_data::to_bytes(&Nanites { injects })
107}
108
109type Subscription = (String, i32, fn(&mut Hook));
111
112pub fn subscribe(registry: &mut Registry) {
114 let entries: Vec<Subscription> = __yog_nanite_registry()
115 .lock()
116 .iter()
117 .filter_map(|e| Some((e.spec().point, e.priority, e.handler?)))
118 .collect();
119 for (key, priority, handler) in entries {
120 registry.change_key_at::<Injected>(&key, priority, move |e, _| handler(&mut Hook(e)));
121 }
122}
123
124pub struct Hook<'a>(&'a mut Injected);
126
127impl<'a> Hook<'a> {
128 pub fn new(e: &'a mut Injected) -> Self {
130 Hook(e)
131 }
132
133 pub fn this<T: Nanite>(&self) -> Option<T> {
135 T::from_value(self.0.this.clone())
136 }
137
138 pub fn arg<T: Java>(&self, i: usize) -> Option<T> {
140 T::from_value(self.0.args.get(i)?.clone())
141 }
142
143 pub fn args(&self) -> usize {
145 self.0.args.len()
146 }
147
148 pub fn value<T: Java>(&self) -> Option<T> {
150 T::from_value(self.0.value.clone())
151 }
152
153 pub fn cancel(&mut self) {
155 self.0.cancelled = true;
156 }
157
158 pub fn set_return<T: Java>(&mut self, value: T) {
160 self.0.value = value.to_value();
161 self.0.cancelled = true;
162 self.0.returned = true;
163 }
164
165 pub fn set_value<T: Java>(&mut self, value: T) {
167 self.0.value = value.to_value();
168 self.0.returned = true;
169 }
170
171 pub fn call_original(&self, args: Vec<yog_data::Value>) -> Option<yog_data::Value> {
173 static APPLY: Member = Member::new(ORIGINAL_CLASS, ORIGINAL_METHOD, original_desc);
174 APPLY.call(self.0.original.clone(), vec![yog_data::Value::List(args)])
175 }
176
177 pub fn cancelled(&self) -> bool {
179 self.0.cancelled
180 }
181}