1use jni::JNIEnv;
30use jni::objects::{JClass, JString};
31use jni::sys::{jlong, jboolean, jint, jstring};
32use dashmap::DashSet;
33
34use crate::validation::{
35 RiValidationError, RiValidationResult, RiValidationSeverity,
36 RiSanitizer, RiSanitizationConfig, RiSchemaValidator,
37 RiValidatorBuilder, RiValidationRunner,
38};
39
40lazy_static::lazy_static! {
41 static ref VALIDATION_MODULE_REGISTRY: DashSet<usize> = DashSet::new();
42 static ref VALIDATION_ERROR_REGISTRY: DashSet<usize> = DashSet::new();
43 static ref VALIDATION_RESULT_REGISTRY: DashSet<usize> = DashSet::new();
44 static ref SANITIZATION_CONFIG_REGISTRY: DashSet<usize> = DashSet::new();
45 static ref SANITIZER_REGISTRY: DashSet<usize> = DashSet::new();
46 static ref SCHEMA_VALIDATOR_REGISTRY: DashSet<usize> = DashSet::new();
47 static ref VALIDATION_RUNNER_REGISTRY: DashSet<usize> = DashSet::new();
48 static ref VALIDATOR_BUILDER_REGISTRY: DashSet<usize> = DashSet::new();
49}
50
51fn register_ptr(registry: &DashSet<usize>, ptr: usize) {
52 registry.insert(ptr);
53}
54
55fn unregister_ptr(registry: &DashSet<usize>, ptr: usize) -> bool {
56 registry.remove(&ptr).is_some()
57}
58
59fn is_valid_ptr(registry: &DashSet<usize>, ptr: usize) -> bool {
60 ptr != 0 && registry.contains(&ptr)
61}
62
63fn box_result(result: RiValidationResult) -> jlong {
68 let result = Box::new(result);
69 let result_ptr = Box::into_raw(result) as jlong;
70 register_ptr(&VALIDATION_RESULT_REGISTRY, result_ptr as usize);
71 result_ptr
72}
73
74fn get_string_arg(env: &mut JNIEnv, s: &JString, arg: &str) -> Option<String> {
75 match env.get_string(s) {
76 Ok(v) => Some(v.into()),
77 Err(_) => {
78 let _ = env.throw_new(
79 "java/lang/IllegalArgumentException",
80 &format!("Failed to get {} string", arg),
81 );
82 None
83 }
84 }
85}
86
87#[no_mangle]
88pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_nativeValidateEmail(
89 mut env: JNIEnv,
90 _class: JClass,
91 email: JString,
92) -> jlong {
93 let Some(email) = get_string_arg(&mut env, &email, "email") else { return 0 };
94 let result = RiValidatorBuilder::new("email")
95 .is_email()
96 .max_length(255)
97 .build()
98 .validate_value(Some(&email));
99 box_result(result)
100}
101
102#[no_mangle]
103pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_nativeValidateUsername(
104 mut env: JNIEnv,
105 _class: JClass,
106 username: JString,
107) -> jlong {
108 let Some(username) = get_string_arg(&mut env, &username, "username") else { return 0 };
109 let result = RiValidatorBuilder::new("username")
110 .not_empty()
111 .min_length(3)
112 .max_length(32)
113 .alphanumeric()
114 .build()
115 .validate_value(Some(&username));
116 box_result(result)
117}
118
119#[no_mangle]
120pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_nativeValidatePassword(
121 mut env: JNIEnv,
122 _class: JClass,
123 password: JString,
124) -> jlong {
125 let Some(password) = get_string_arg(&mut env, &password, "password") else { return 0 };
126 let result = RiValidatorBuilder::new("password")
127 .not_empty()
128 .min_length(8)
129 .build()
130 .validate_value(Some(&password));
131 box_result(result)
132}
133
134#[no_mangle]
135pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_nativeValidateUrl(
136 mut env: JNIEnv,
137 _class: JClass,
138 url: JString,
139) -> jlong {
140 let Some(url) = get_string_arg(&mut env, &url, "url") else { return 0 };
141 let result = RiValidatorBuilder::new("url")
142 .is_url()
143 .build()
144 .validate_value(Some(&url));
145 box_result(result)
146}
147
148#[no_mangle]
149pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationModule_nativeValidateIp(
150 mut env: JNIEnv,
151 _class: JClass,
152 ip: JString,
153) -> jlong {
154 let Some(ip) = get_string_arg(&mut env, &ip, "ip") else { return 0 };
155 let result = RiValidatorBuilder::new("ip")
156 .is_ip()
157 .build()
158 .validate_value(Some(&ip));
159 box_result(result)
160}
161
162#[no_mangle]
167pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getField0<'local>(
168 mut env: JNIEnv<'local>,
169 _class: JClass<'local>,
170 ptr: jlong,
171) -> jstring {
172 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
173 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
174 .unwrap_or(());
175 return std::ptr::null_mut();
176 }
177
178 let error = unsafe { &*(ptr as *const RiValidationError) };
179 match env.new_string(&error.field) {
180 Ok(s) => s.into_raw(),
181 Err(_) => std::ptr::null_mut(),
182 }
183}
184
185#[no_mangle]
186pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getMessage0<'local>(
187 mut env: JNIEnv<'local>,
188 _class: JClass<'local>,
189 ptr: jlong,
190) -> jstring {
191 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
192 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
193 .unwrap_or(());
194 return std::ptr::null_mut();
195 }
196
197 let error = unsafe { &*(ptr as *const RiValidationError) };
198 match env.new_string(&error.message) {
199 Ok(s) => s.into_raw(),
200 Err(_) => std::ptr::null_mut(),
201 }
202}
203
204#[no_mangle]
205pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getCode0<'local>(
206 mut env: JNIEnv<'local>,
207 _class: JClass<'local>,
208 ptr: jlong,
209) -> jstring {
210 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
211 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
212 .unwrap_or(());
213 return std::ptr::null_mut();
214 }
215
216 let error = unsafe { &*(ptr as *const RiValidationError) };
217 match env.new_string(&error.code) {
218 Ok(s) => s.into_raw(),
219 Err(_) => std::ptr::null_mut(),
220 }
221}
222
223#[no_mangle]
224pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_getSeverity0(
225 mut env: JNIEnv,
226 _class: JClass,
227 ptr: jlong,
228) -> jint {
229 if !is_valid_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
230 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationError pointer")
231 .unwrap_or(());
232 return 0;
233 }
234
235 let error = unsafe { &*(ptr as *const RiValidationError) };
236 match error.severity.clone() {
237 RiValidationSeverity::Error => 0,
238 RiValidationSeverity::Warning => 1,
239 RiValidationSeverity::Info => 2,
240 RiValidationSeverity::Critical => 3,
241 }
242}
243
244#[no_mangle]
245pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationError_free0(
246 _env: JNIEnv,
247 _class: JClass,
248 ptr: jlong,
249) {
250 if unregister_ptr(&VALIDATION_ERROR_REGISTRY, ptr as usize) {
251 unsafe {
252 let _ = Box::from_raw(ptr as *mut RiValidationError);
253 }
254 }
255}
256
257#[no_mangle]
262pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationResult_isValid0(
263 mut env: JNIEnv,
264 _class: JClass,
265 ptr: jlong,
266) -> jboolean {
267 if !is_valid_ptr(&VALIDATION_RESULT_REGISTRY, ptr as usize) {
268 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationResult pointer")
269 .unwrap_or(());
270 return 0;
271 }
272
273 let result = unsafe { &*(ptr as *const RiValidationResult) };
274 result.is_valid as jboolean
275}
276
277#[no_mangle]
278pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationResult_free0(
279 _env: JNIEnv,
280 _class: JClass,
281 ptr: jlong,
282) {
283 if unregister_ptr(&VALIDATION_RESULT_REGISTRY, ptr as usize) {
284 unsafe {
285 let _ = Box::from_raw(ptr as *mut RiValidationResult);
286 }
287 }
288}
289
290#[no_mangle]
295pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_new0(
296 _env: JNIEnv,
297 _class: JClass,
298) -> jlong {
299 let config = Box::new(RiSanitizationConfig::default());
300 let ptr = Box::into_raw(config) as jlong;
301 register_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize);
302 ptr
303}
304
305#[no_mangle]
306pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isTrimWhitespace0(
307 mut env: JNIEnv,
308 _class: JClass,
309 ptr: jlong,
310) -> jboolean {
311 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
312 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
313 .unwrap_or(());
314 return 0;
315 }
316
317 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
318 config.trim_whitespace as jboolean
319}
320
321#[no_mangle]
322pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setTrimWhitespace0(
323 mut env: JNIEnv,
324 _class: JClass,
325 ptr: jlong,
326 enabled: jboolean,
327) {
328 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
329 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
330 .unwrap_or(());
331 return;
332 }
333
334 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
335 config.trim_whitespace = enabled != 0;
336}
337
338#[no_mangle]
339pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isLowercase0(
340 mut env: JNIEnv,
341 _class: JClass,
342 ptr: jlong,
343) -> jboolean {
344 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
345 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
346 .unwrap_or(());
347 return 0;
348 }
349
350 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
351 config.lowercase as jboolean
352}
353
354#[no_mangle]
355pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setLowercase0(
356 mut env: JNIEnv,
357 _class: JClass,
358 ptr: jlong,
359 enabled: jboolean,
360) {
361 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
362 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
363 .unwrap_or(());
364 return;
365 }
366
367 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
368 config.lowercase = enabled != 0;
369}
370
371#[no_mangle]
372pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isUppercase0(
373 mut env: JNIEnv,
374 _class: JClass,
375 ptr: jlong,
376) -> jboolean {
377 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
378 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
379 .unwrap_or(());
380 return 0;
381 }
382
383 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
384 config.uppercase as jboolean
385}
386
387#[no_mangle]
388pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setUppercase0(
389 mut env: JNIEnv,
390 _class: JClass,
391 ptr: jlong,
392 enabled: jboolean,
393) {
394 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
395 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
396 .unwrap_or(());
397 return;
398 }
399
400 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
401 config.uppercase = enabled != 0;
402}
403
404#[no_mangle]
405pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isRemoveHtmlTags0(
406 mut env: JNIEnv,
407 _class: JClass,
408 ptr: jlong,
409) -> jboolean {
410 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
411 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
412 .unwrap_or(());
413 return 0;
414 }
415
416 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
417 config.remove_html_tags as jboolean
418}
419
420#[no_mangle]
421pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setRemoveHtmlTags0(
422 mut env: JNIEnv,
423 _class: JClass,
424 ptr: jlong,
425 enabled: jboolean,
426) {
427 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
428 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
429 .unwrap_or(());
430 return;
431 }
432
433 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
434 config.remove_html_tags = enabled != 0;
435}
436
437#[no_mangle]
438pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_isEscapeSpecialChars0(
439 mut env: JNIEnv,
440 _class: JClass,
441 ptr: jlong,
442) -> jboolean {
443 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
444 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
445 .unwrap_or(());
446 return 0;
447 }
448
449 let config = unsafe { &*(ptr as *const RiSanitizationConfig) };
450 config.escape_special_chars as jboolean
451}
452
453#[no_mangle]
454pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_setEscapeSpecialChars0(
455 mut env: JNIEnv,
456 _class: JClass,
457 ptr: jlong,
458 enabled: jboolean,
459) {
460 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
461 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
462 .unwrap_or(());
463 return;
464 }
465
466 let config = unsafe { &mut *(ptr as *mut RiSanitizationConfig) };
467 config.escape_special_chars = enabled != 0;
468}
469
470#[no_mangle]
471pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizationConfig_free0(
472 _env: JNIEnv,
473 _class: JClass,
474 ptr: jlong,
475) {
476 if unregister_ptr(&SANITIZATION_CONFIG_REGISTRY, ptr as usize) {
477 unsafe {
478 let _ = Box::from_raw(ptr as *mut RiSanitizationConfig);
479 }
480 }
481}
482
483#[no_mangle]
488pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_new0(
489 _env: JNIEnv,
490 _class: JClass,
491) -> jlong {
492 let sanitizer = Box::new(RiSanitizer::new());
493 let ptr = Box::into_raw(sanitizer) as jlong;
494 register_ptr(&SANITIZER_REGISTRY, ptr as usize);
495 ptr
496}
497
498#[no_mangle]
499pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_newWithConfig0(
500 mut env: JNIEnv,
501 _class: JClass,
502 config_ptr: jlong,
503) -> jlong {
504 if !is_valid_ptr(&SANITIZATION_CONFIG_REGISTRY, config_ptr as usize) {
505 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizationConfig pointer")
506 .unwrap_or(());
507 return 0;
508 }
509
510 let config = unsafe { &*(config_ptr as *const RiSanitizationConfig) };
511 let sanitizer = Box::new(RiSanitizer::with_config(config.clone()));
512 let ptr = Box::into_raw(sanitizer) as jlong;
513 register_ptr(&SANITIZER_REGISTRY, ptr as usize);
514 ptr
515}
516
517#[no_mangle]
518pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitize0<'local>(
519 mut env: JNIEnv<'local>,
520 _class: JClass<'local>,
521 ptr: jlong,
522 input: JString,
523) -> jstring {
524 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
525 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
526 .unwrap_or(());
527 return std::ptr::null_mut();
528 }
529
530 let input_str: String = match env.get_string(&input) {
531 Ok(s) => s.into(),
532 Err(_) => {
533 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
534 .unwrap_or(());
535 return std::ptr::null_mut();
536 }
537 };
538
539 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
540 let result = sanitizer.sanitize(&input_str);
541 match env.new_string(&result) {
542 Ok(s) => s.into_raw(),
543 Err(_) => std::ptr::null_mut(),
544 }
545}
546
547#[no_mangle]
548pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitizeEmail0<'local>(
549 mut env: JNIEnv<'local>,
550 _class: JClass<'local>,
551 ptr: jlong,
552 input: JString,
553) -> jstring {
554 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
555 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
556 .unwrap_or(());
557 return std::ptr::null_mut();
558 }
559
560 let input_str: String = match env.get_string(&input) {
561 Ok(s) => s.into(),
562 Err(_) => {
563 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
564 .unwrap_or(());
565 return std::ptr::null_mut();
566 }
567 };
568
569 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
570 let result = sanitizer.sanitize_email(&input_str);
571 match env.new_string(&result) {
572 Ok(s) => s.into_raw(),
573 Err(_) => std::ptr::null_mut(),
574 }
575}
576
577#[no_mangle]
578pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_sanitizeFilename0<'local>(
579 mut env: JNIEnv<'local>,
580 _class: JClass<'local>,
581 ptr: jlong,
582 input: JString,
583) -> jstring {
584 if !is_valid_ptr(&SANITIZER_REGISTRY, ptr as usize) {
585 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSanitizer pointer")
586 .unwrap_or(());
587 return std::ptr::null_mut();
588 }
589
590 let input_str: String = match env.get_string(&input) {
591 Ok(s) => s.into(),
592 Err(_) => {
593 env.throw_new("java/lang/IllegalArgumentException", "Failed to get input string")
594 .unwrap_or(());
595 return std::ptr::null_mut();
596 }
597 };
598
599 let sanitizer = unsafe { &*(ptr as *const RiSanitizer) };
600 let result = sanitizer.sanitize_filename(&input_str);
601 match env.new_string(&result) {
602 Ok(s) => s.into_raw(),
603 Err(_) => std::ptr::null_mut(),
604 }
605}
606
607#[no_mangle]
608pub extern "system" fn Java_com_dunimd_ri_validation_RiSanitizer_free0(
609 _env: JNIEnv,
610 _class: JClass,
611 ptr: jlong,
612) {
613 if unregister_ptr(&SANITIZER_REGISTRY, ptr as usize) {
614 unsafe {
615 let _ = Box::from_raw(ptr as *mut RiSanitizer);
616 }
617 }
618}
619
620#[no_mangle]
625pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_new0(
626 mut env: JNIEnv,
627 _class: JClass,
628 schema_json: JString,
629) -> jlong {
630 let schema_str: String = match env.get_string(&schema_json) {
631 Ok(s) => s.into(),
632 Err(_) => {
633 env.throw_new("java/lang/IllegalArgumentException", "Failed to get schema string")
634 .unwrap_or(());
635 return 0;
636 }
637 };
638
639 let schema_value: serde_json::Value = match serde_json::from_str(&schema_str) {
640 Ok(v) => v,
641 Err(e) => {
642 let _ = env.throw_new(
643 "java/lang/IllegalArgumentException",
644 &format!("Failed to parse schema JSON: {}", e),
645 );
646 return 0;
647 }
648 };
649
650 let validator = RiSchemaValidator::new(schema_value);
651 let ptr = Box::into_raw(Box::new(validator)) as jlong;
652 register_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize);
653 ptr
654}
655
656#[no_mangle]
657pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_validate0(
658 mut env: JNIEnv,
659 _class: JClass,
660 ptr: jlong,
661 data_json: JString,
662) -> jlong {
663 if !is_valid_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize) {
664 env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiSchemaValidator pointer")
665 .unwrap_or(());
666 return 0;
667 }
668
669 let data_str: String = match env.get_string(&data_json) {
670 Ok(s) => s.into(),
671 Err(_) => {
672 env.throw_new("java/lang/IllegalArgumentException", "Failed to get data string")
673 .unwrap_or(());
674 return 0;
675 }
676 };
677
678 let validator = unsafe { &*(ptr as *const RiSchemaValidator) };
679 let data_value: serde_json::Value = match serde_json::from_str(&data_str) {
680 Ok(v) => v,
681 Err(_) => serde_json::Value::Null,
682 };
683 let result = Box::new(validator.validate(&data_value));
684 let result_ptr = Box::into_raw(result) as jlong;
685 register_ptr(&VALIDATION_RESULT_REGISTRY, result_ptr as usize);
686 result_ptr
687}
688
689#[no_mangle]
690pub extern "system" fn Java_com_dunimd_ri_validation_RiSchemaValidator_free0(
691 _env: JNIEnv,
692 _class: JClass,
693 ptr: jlong,
694) {
695 if unregister_ptr(&SCHEMA_VALIDATOR_REGISTRY, ptr as usize) {
696 unsafe {
697 let _ = Box::from_raw(ptr as *mut RiSchemaValidator);
698 }
699 }
700}
701
702#[no_mangle]
707pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationRunner_validate0(
708 mut env: JNIEnv,
709 _class: JClass,
710 ptr: jlong,
711 value: JString,
712) -> jlong {
713 if !is_valid_ptr(&VALIDATION_RUNNER_REGISTRY, ptr as usize) {
714 let _ = env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidationRunner pointer");
715 return 0;
716 }
717
718 let value_str = match get_string_arg(&mut env, &value, "value") {
719 Some(v) => v,
720 None => return 0,
721 };
722
723 let runner = unsafe { &*(ptr as *const RiValidationRunner) };
724 box_result(runner.validate_value(Some(&value_str)))
725}
726
727#[no_mangle]
728pub extern "system" fn Java_com_dunimd_ri_validation_RiValidationRunner_free0(
729 _env: JNIEnv,
730 _class: JClass,
731 ptr: jlong,
732) {
733 if unregister_ptr(&VALIDATION_RUNNER_REGISTRY, ptr as usize) {
734 unsafe {
735 let _ = Box::from_raw(ptr as *mut RiValidationRunner);
736 }
737 }
738}
739
740pub struct BuilderSlot {
748 inner: std::sync::Mutex<Option<RiValidatorBuilder>>,
749}
750
751fn builder_slot_valid(env: &mut JNIEnv, ptr: jlong) -> bool {
752 if !is_valid_ptr(&VALIDATOR_BUILDER_REGISTRY, ptr as usize) {
753 let _ = env.throw_new("java/lang/IllegalStateException", "Invalid or freed RiValidatorBuilder pointer");
754 return false;
755 }
756 true
757}
758
759fn modify_builder(
760 env: &mut JNIEnv,
761 ptr: jlong,
762 f: impl FnOnce(RiValidatorBuilder) -> RiValidatorBuilder,
763) {
764 if !builder_slot_valid(env, ptr) {
765 return;
766 }
767 let slot = unsafe { &*(ptr as *const BuilderSlot) };
768 if let Ok(mut guard) = slot.inner.lock() {
769 if let Some(builder) = guard.take() {
770 *guard = Some(f(builder));
771 }
772 }
773}
774
775#[no_mangle]
776pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_new0(
777 mut env: JNIEnv,
778 _class: JClass,
779 field_name: JString,
780) -> jlong {
781 let Some(field_name) = get_string_arg(&mut env, &field_name, "fieldName") else { return 0 };
782 let slot = Box::new(BuilderSlot {
783 inner: std::sync::Mutex::new(Some(RiValidatorBuilder::new(&field_name))),
784 });
785 let ptr = Box::into_raw(slot) as jlong;
786 register_ptr(&VALIDATOR_BUILDER_REGISTRY, ptr as usize);
787 ptr
788}
789
790#[no_mangle]
791pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_notEmpty0(
792 mut env: JNIEnv,
793 _class: JClass,
794 ptr: jlong,
795) {
796 modify_builder(&mut env, ptr, |b| b.not_empty());
797}
798
799#[no_mangle]
800pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_minLength0(
801 mut env: JNIEnv,
802 _class: JClass,
803 ptr: jlong,
804 min: jint,
805) {
806 modify_builder(&mut env, ptr, |b| b.min_length(min.max(0) as usize));
807}
808
809#[no_mangle]
810pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_maxLength0(
811 mut env: JNIEnv,
812 _class: JClass,
813 ptr: jlong,
814 max: jint,
815) {
816 modify_builder(&mut env, ptr, |b| b.max_length(max.max(0) as usize));
817}
818
819#[no_mangle]
820pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_isEmail0(
821 mut env: JNIEnv,
822 _class: JClass,
823 ptr: jlong,
824) {
825 modify_builder(&mut env, ptr, |b| b.is_email());
826}
827
828#[no_mangle]
829pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_build0(
830 mut env: JNIEnv,
831 _class: JClass,
832 ptr: jlong,
833) -> jlong {
834 if !builder_slot_valid(&mut env, ptr) {
835 return 0;
836 }
837 let slot = unsafe { &*(ptr as *const BuilderSlot) };
838 let builder = match slot.inner.lock() {
839 Ok(mut guard) => guard.take(),
840 Err(_) => None,
841 };
842 match builder {
843 Some(builder) => {
844 let runner = builder.build();
845 let runner_ptr = Box::into_raw(Box::new(runner)) as jlong;
846 register_ptr(&VALIDATION_RUNNER_REGISTRY, runner_ptr as usize);
847 runner_ptr
848 }
849 None => {
850 let _ = env.throw_new("java/lang/IllegalStateException", "RiValidatorBuilder already consumed");
851 0
852 }
853 }
854}
855
856#[no_mangle]
857pub extern "system" fn Java_com_dunimd_ri_validation_RiValidatorBuilder_free0(
858 _env: JNIEnv,
859 _class: JClass,
860 ptr: jlong,
861) {
862 if unregister_ptr(&VALIDATOR_BUILDER_REGISTRY, ptr as usize) {
863 unsafe {
864 let _ = Box::from_raw(ptr as *mut BuilderSlot);
865 }
866 }
867}