Skip to main content

ri/java/classes/
module_rpc.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18//! # Module RPC JNI Bindings
19//!
20//! JNI bindings for Ri module RPC classes.
21
22use jni::JNIEnv;
23use jni::objects::{JClass, JString};
24use jni::sys::{jlong, jboolean, jbyteArray, jstring};
25use crate::module_rpc::{RiModuleRPC, RiModuleEndpoint, RiMethodCall, RiMethodResponse};
26use crate::java::exception::check_not_null;
27
28// =============================================================================
29// RiModuleRPC JNI Bindings
30// =============================================================================
31
32#[no_mangle]
33pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleRPC_new0(
34    _env: JNIEnv,
35    _class: JClass,
36) -> jlong {
37    let rpc = Box::new(RiModuleRPC::new());
38    Box::into_raw(rpc) as jlong
39}
40
41#[no_mangle]
42pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleRPC_registerModule0(
43    mut env: JNIEnv,
44    _class: JClass,
45    ptr: jlong,
46    module_name: JString,
47) -> jboolean {
48    if !check_not_null(&mut env, ptr, "RiModuleRPC") {
49        return 0;
50    }
51    
52    let module_name_str: String = env.get_string(&module_name)
53        .expect("Failed to get module name")
54        .into();
55    
56    let rpc = unsafe { &mut *(ptr as *mut RiModuleRPC) };
57    rpc.register_module(&module_name_str).is_ok() as jboolean
58}
59
60#[no_mangle]
61pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleRPC_unregisterModule0(
62    mut env: JNIEnv,
63    _class: JClass,
64    ptr: jlong,
65    module_name: JString,
66) -> jboolean {
67    if !check_not_null(&mut env, ptr, "RiModuleRPC") {
68        return 0;
69    }
70    
71    let module_name_str: String = env.get_string(&module_name)
72        .expect("Failed to get module name")
73        .into();
74    
75    let rpc = unsafe { &mut *(ptr as *mut RiModuleRPC) };
76    rpc.unregister_module(&module_name_str).is_ok() as jboolean
77}
78
79#[no_mangle]
80pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleRPC_isModuleRegistered0(
81    mut env: JNIEnv,
82    _class: JClass,
83    ptr: jlong,
84    module_name: JString,
85) -> jboolean {
86    if !check_not_null(&mut env, ptr, "RiModuleRPC") {
87        return 0;
88    }
89    
90    let module_name_str: String = env.get_string(&module_name)
91        .expect("Failed to get module name")
92        .into();
93    
94    let rpc = unsafe { &*(ptr as *const RiModuleRPC) };
95    rpc.is_module_registered(&module_name_str) as jboolean
96}
97
98#[no_mangle]
99pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleRPC_free0(
100    _env: JNIEnv,
101    _class: JClass,
102    ptr: jlong,
103) {
104    if ptr != 0 {
105        unsafe {
106            let _ = Box::from_raw(ptr as *mut RiModuleRPC);
107        }
108    }
109}
110
111// =============================================================================
112// RiModuleClient JNI Bindings
113// =============================================================================
114
115#[no_mangle]
116pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleClient_new0(
117    mut env: JNIEnv,
118    _class: JClass,
119    rpc_ptr: jlong,
120) -> jlong {
121    if !check_not_null(&mut env, rpc_ptr, "RiModuleRPC") {
122        return 0;
123    }
124    0
125}
126
127#[no_mangle]
128pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleClient_call0(
129    mut env: JNIEnv,
130    _class: JClass,
131    ptr: jlong,
132    module_name: JString,
133    method_name: JString,
134    params: jbyteArray,
135) -> jlong {
136    if !check_not_null(&mut env, ptr, "RiModuleClient") {
137        return 0;
138    }
139    
140    let _module_name_str: String = env.get_string(&module_name)
141        .expect("Failed to get module name")
142        .into();
143    let _method_name_str: String = env.get_string(&method_name)
144        .expect("Failed to get method name")
145        .into();
146    
147    let response = Box::new(RiMethodResponse::success(vec![]));
148    Box::into_raw(response) as jlong
149}
150
151#[no_mangle]
152pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleClient_callWithTimeout0(
153    mut env: JNIEnv,
154    _class: JClass,
155    ptr: jlong,
156    module_name: JString,
157    method_name: JString,
158    params: jbyteArray,
159    timeout_ms: jlong,
160) -> jlong {
161    if !check_not_null(&mut env, ptr, "RiModuleClient") {
162        return 0;
163    }
164    
165    let _module_name_str: String = env.get_string(&module_name)
166        .expect("Failed to get module name")
167        .into();
168    let _method_name_str: String = env.get_string(&method_name)
169        .expect("Failed to get method name")
170        .into();
171    
172    let response = Box::new(RiMethodResponse::success(vec![]));
173    Box::into_raw(response) as jlong
174}
175
176#[no_mangle]
177pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleClient_free0(
178    _env: JNIEnv,
179    _class: JClass,
180    ptr: jlong,
181) {
182}
183
184// =============================================================================
185// RiModuleEndpoint JNI Bindings
186// =============================================================================
187
188#[no_mangle]
189pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleEndpoint_new0(
190    mut env: JNIEnv,
191    _class: JClass,
192    module_name: JString,
193) -> jlong {
194    let module_name_str: String = env.get_string(&module_name)
195        .expect("Failed to get module name")
196        .into();
197    
198    let endpoint = Box::new(RiModuleEndpoint::new(module_name_str));
199    Box::into_raw(endpoint) as jlong
200}
201
202#[no_mangle]
203pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleEndpoint_getModuleName0<'local>(
204    mut env: JNIEnv<'local>,
205    _class: JClass<'local>,
206    ptr: jlong,
207) -> jstring {
208    if !check_not_null(&mut env, ptr, "RiModuleEndpoint") {
209        return std::ptr::null_mut();
210    }
211    
212    let endpoint = unsafe { &*(ptr as *const RiModuleEndpoint) };
213    env.new_string(endpoint.module_name()).unwrap().into_raw()
214}
215
216#[no_mangle]
217pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleEndpoint_listMethods0(
218    mut env: JNIEnv,
219    _class: JClass,
220    ptr: jlong,
221) -> jstring {
222    if !check_not_null(&mut env, ptr, "RiModuleEndpoint") {
223        return std::ptr::null_mut();
224    }
225    
226    let endpoint = unsafe { &*(ptr as *const RiModuleEndpoint) };
227    let methods = endpoint.list_methods();
228    let json = serde_json::to_string(&methods).unwrap_or("[]".to_string());
229    env.new_string(&json).unwrap().into_raw()
230}
231
232#[no_mangle]
233pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiModuleEndpoint_free0(
234    _env: JNIEnv,
235    _class: JClass,
236    ptr: jlong,
237) {
238    if ptr != 0 {
239        unsafe {
240            let _ = Box::from_raw(ptr as *mut RiModuleEndpoint);
241        }
242    }
243}
244
245// =============================================================================
246// RiMethodCall JNI Bindings
247// =============================================================================
248
249#[no_mangle]
250pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_new0(
251    mut env: JNIEnv,
252    _class: JClass,
253    method_name: JString,
254    params: jbyteArray,
255) -> jlong {
256    let method_name_str: String = env.get_string(&method_name)
257        .expect("Failed to get method name")
258        .into();
259    
260    let params_vec: Vec<u8> = if !params.is_null() {
261        env.convert_byte_array(params).unwrap_or_default()
262    } else {
263        Vec::new()
264    };
265    
266    let call = Box::new(RiMethodCall::new(method_name_str, params_vec));
267    Box::into_raw(call) as jlong
268}
269
270#[no_mangle]
271pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_getMethodName0<'local>(
272    mut env: JNIEnv<'local>,
273    _class: JClass<'local>,
274    ptr: jlong,
275) -> jstring {
276    if !check_not_null(&mut env, ptr, "RiMethodCall") {
277        return std::ptr::null_mut();
278    }
279    
280    let call = unsafe { &*(ptr as *const RiMethodCall) };
281    env.new_string(call.method_name()).unwrap().into_raw()
282}
283
284#[no_mangle]
285pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_getParams0(
286    mut env: JNIEnv,
287    _class: JClass,
288    ptr: jlong,
289) -> jbyteArray {
290    if !check_not_null(&mut env, ptr, "RiMethodCall") {
291        return std::ptr::null_mut();
292    }
293    
294    let call = unsafe { &*(ptr as *const RiMethodCall) };
295    let params = call.params();
296    
297    let array = env.new_byte_array(params.len() as i32).unwrap();
298    env.set_byte_array_region(&array, 0, unsafe { 
299        std::slice::from_raw_parts(params.as_ptr() as *const i8, params.len()) 
300    }).unwrap();
301    array.into_raw()
302}
303
304#[no_mangle]
305pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_getTimeoutMs0(
306    mut env: JNIEnv,
307    _class: JClass,
308    ptr: jlong,
309) -> jlong {
310    if !check_not_null(&mut env, ptr, "RiMethodCall") {
311        return 0;
312    }
313    
314    let call = unsafe { &*(ptr as *const RiMethodCall) };
315    call.timeout_ms() as jlong
316}
317
318#[no_mangle]
319pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_setTimeoutMs0(
320    mut env: JNIEnv,
321    _class: JClass,
322    ptr: jlong,
323    timeout_ms: jlong,
324) {
325    if !check_not_null(&mut env, ptr, "RiMethodCall") {
326        return;
327    }
328    
329    let call = unsafe { &mut *(ptr as *mut RiMethodCall) };
330    call.set_timeout_ms(timeout_ms as u64);
331}
332
333#[no_mangle]
334pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodCall_free0(
335    _env: JNIEnv,
336    _class: JClass,
337    ptr: jlong,
338) {
339    if ptr != 0 {
340        unsafe {
341            let _ = Box::from_raw(ptr as *mut RiMethodCall);
342        }
343    }
344}
345
346// =============================================================================
347// RiMethodResponse JNI Bindings
348// =============================================================================
349
350#[no_mangle]
351pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodResponse_isSuccess0(
352    mut env: JNIEnv,
353    _class: JClass,
354    ptr: jlong,
355) -> jboolean {
356    if !check_not_null(&mut env, ptr, "RiMethodResponse") {
357        return 0;
358    }
359    
360    let response = unsafe { &*(ptr as *const RiMethodResponse) };
361    response.is_success() as jboolean
362}
363
364#[no_mangle]
365pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodResponse_getData0(
366    mut env: JNIEnv,
367    _class: JClass,
368    ptr: jlong,
369) -> jbyteArray {
370    if !check_not_null(&mut env, ptr, "RiMethodResponse") {
371        return std::ptr::null_mut();
372    }
373    
374    let response = unsafe { &*(ptr as *const RiMethodResponse) };
375    let data = response.data();
376    
377    let array = env.new_byte_array(data.len() as i32).unwrap();
378    env.set_byte_array_region(&array, 0, unsafe { 
379        std::slice::from_raw_parts(data.as_ptr() as *const i8, data.len()) 
380    }).unwrap();
381    array.into_raw()
382}
383
384#[no_mangle]
385pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodResponse_getError0<'local>(
386    mut env: JNIEnv<'local>,
387    _class: JClass<'local>,
388    ptr: jlong,
389) -> jstring {
390    if !check_not_null(&mut env, ptr, "RiMethodResponse") {
391        return std::ptr::null_mut();
392    }
393    
394    let response = unsafe { &*(ptr as *const RiMethodResponse) };
395    match response.error() {
396        Some(err) => env.new_string(err).unwrap().into_raw(),
397        None => std::ptr::null_mut(),
398    }
399}
400
401#[no_mangle]
402pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodResponse_isTimeout0(
403    mut env: JNIEnv,
404    _class: JClass,
405    ptr: jlong,
406) -> jboolean {
407    if !check_not_null(&mut env, ptr, "RiMethodResponse") {
408        return 0;
409    }
410    
411    let response = unsafe { &*(ptr as *const RiMethodResponse) };
412    response.is_timeout() as jboolean
413}
414
415#[no_mangle]
416pub extern "system" fn Java_com_dunimd_ri_modulerpc_RiMethodResponse_free0(
417    _env: JNIEnv,
418    _class: JClass,
419    ptr: jlong,
420) {
421    if ptr != 0 {
422        unsafe {
423            let _ = Box::from_raw(ptr as *mut RiMethodResponse);
424        }
425    }
426}