1#[macro_export]
43macro_rules! split_by_comma {
44 (
47 {$($input:tt)*},
48 $macro:path $(,$args:tt)*
49 ) => {
50 $crate::split_by_comma! {
51 {$($input)*},
52 {}, {}, $macro $(,$args)*
55 }
56 };
57 (
61 {
62 ,
63 $($rest:tt)*
64 },
65 {
66 $(
67 {$($prev_split:tt)*}
68 )*
69 },
70 {
71 $($current_split:tt)*
72 },
73 $macro:path $(,$args:tt)*
74 ) => {
75 $crate::split_by_comma! {
76 {
77 $($rest)*
78 },
79 {
80 $(
81 {$($prev_split)*}
82 )*
83 {
84 $($current_split)*
85 }
86 },
87 {},
88 $macro $(,$args)*
89 }
90 };
91 (
94 {},
95 {
96 $(
97 {$($prev_split:tt)*}
98 )*
99 },
100 {
101 $($current_split:tt)+
102 },
103 $macro:path $(,$args:tt)*
104 ) => {
105 $crate::split_by_comma! {
106 {},
107 {
108 $(
109 {$($prev_split)*}
110 )*
111 {
112 $($current_split)+
113 }
114 },
115 {},
116 $macro $(,$args)*
117 }
118 };
119 (
121 {
122 $first:tt
123 $($rest:tt)*
124 },
125 {
126 $(
127 {$($prev_split:tt)*}
128 )*
129 },
130 {
131 $($current_split:tt)*
132 },
133 $macro:path $(,$args:tt)*
134 ) => {
135 $crate::split_by_comma! {
136 {
137 $($rest)*
138 },
139 {
140 $(
141 {$($prev_split)*}
142 )*
143 },
144 {
145 $($current_split)* $first
146 },
147 $macro $(,$args)*
148 }
149 };
150 (
152 {},
153 {
154 $(
155 {$($prev_split:tt)*}
156 )*
157 },
158 {},
159 $macro:path $(,$args:tt)*
160 ) => {
161 $macro! {
162 {
163 $(
164 {$($prev_split)*}
165 )*
166 }
167 $(,$args)*
168 }
169 };
170}
171#[macro_export]
186macro_rules! gen_class_name {
187 ($single_part_class:ident $($param_name:ident)?) => {
189 $crate::gen_class_name! { @inner java.lang.$single_part_class }
190 };
191 ($($class:ident).+ $($param_name:ident)?) => {
192 $crate::gen_class_name! { @inner $($class).+ }
193 };
194 (@inner $last:ident) => {
195 stringify! {$last}
196 };
197 (@inner $first:ident . $($rest:ident).+) => {
198 concat! {stringify! {$first}, "/", $crate::gen_class_name! {@inner $($rest).+} }
199 }
200}
201
202#[macro_export]
219macro_rules! gen_jni_type_sig {
220 (boolean $($param_name:ident)?) => {
221 "Z"
222 };
223 (byte $($param_name:ident)?) => {
224 "B"
225 };
226 (char $($param_name:ident)?) => {
227 "C"
228 };
229 (short $($param_name:ident)?) => {
230 "S"
231 };
232 (int $($param_name:ident)?) => {
233 "I"
234 };
235 (long $($param_name:ident)?) => {
236 "J"
237 };
238 (float $($param_name:ident)?) => {
239 "F"
240 };
241 (double $($param_name:ident)?) => {
242 "D"
243 };
244 (void) => {
245 "V"
246 };
247 (Class $(< ? >)? $($param_name:ident)?) => {
248 $crate::gen_jni_type_sig! { java.lang.Class }
249 };
250 ($($class_part:ident).+ $($param_name:ident)?) => {
251 concat! {"L", $crate::gen_class_name! {$($class_part).+}, ";"}
252 };
253 ($($class_part:ident).+ [] $($param_name:ident)?) => {
254 concat! { "[", $crate::gen_jni_type_sig! {$($class_part).+}}
255 };
256 ($($invalid:tt)*) => {
257 compile_error!(concat!("unsupported type `", stringify!($($invalid)*), "`"))
258 };
259}
260
261#[macro_export]
281macro_rules! cast_jvalue {
282 ({ boolean }, $value:expr) => {{ $value.z().expect("should be bool") }};
283 ({ byte }, $value:expr) => {{ $value.b().expect("should be byte") }};
284 ({ char }, $value:expr) => {{ $value.c().expect("should be char") }};
285 ({ double }, $value:expr) => {{ $value.d().expect("should be double") }};
286 ({ float }, $value:expr) => {{ $value.f().expect("should be float") }};
287 ({ int }, $value:expr) => {{ $value.i().expect("should be int") }};
288 ({ long }, $value:expr) => {{ $value.j().expect("should be long") }};
289 ({ short }, $value:expr) => {{ $value.s().expect("should be short") }};
290 ({ void }, $value:expr) => {{ $value.v().expect("should be void") }};
291 ({ byte[] }, $value:expr) => {{
292 let obj = $value.l().expect("should be object");
293 unsafe { jni::objects::JByteArray::from_raw(obj.into_raw()) }
294 }};
295 ({ $($class:tt)+ }, $value:expr) => {{ $value.l().expect("should be object") }};
296}
297
298#[macro_export]
321macro_rules! to_jvalue {
322 ({ boolean $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Bool($value as _) }};
323 ({ byte $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Byte($value as _) }};
324 ({ char $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Char($value as _) }};
325 ({ double $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Double($value as _) }};
326 ({ float $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Float($value as _) }};
327 ({ int $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Int($value as _) }};
328 ({ long $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Long($value as _) }};
329 ({ short $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Short($value as _) }};
330 ({ void }, $value:expr) => {{
331 compile_error! {concat! {"unlike to pass void value: ", stringify! {$value} }}
332 }};
333 ({ $($class:ident)+ $([])? $($param_name:ident)? }, $value:expr) => {{ jni::objects::JValue::Object($value as _) }};
334}
335
336#[macro_export]
373macro_rules! gen_jni_sig {
374 ({$({$($args:tt)+})*}, {return {$($ret:tt)*}}) => {{
376 concat! {
377 "(", $($crate::gen_jni_type_sig!{ $($args)+ },)* ")",
378 $crate::gen_jni_type_sig! {$($ret)+}
379 }
380 }};
381 ({$($ret:tt)*}, {$($args:tt)*}) => {{
382 $crate::split_by_comma! {
383 {$($args)*},
384 $crate::gen_jni_sig,
385 {return {$($ret)*}}
386 }
387 }};
388 ({{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}}) => {{
390 $crate::gen_jni_sig! {
391 {$($ret)*}, {$($args)*}
392 }
393 }};
394 ($($input:tt)*) => {{
395 $crate::split_extract_plain_native_methods! {{$($input)*;}, $crate::gen_jni_sig}
396 }}
397}
398
399#[macro_export]
400macro_rules! for_all_plain_native_methods {
401 ($macro:path $(,$args:tt)*) => {
402 $macro! {
403 {
404 public static native void tracingSlf4jEvent(String threadName, String name, int level, String message, String stackTrace);
405
406 public static native boolean tracingSlf4jEventEnabled(int level);
407
408 public static native int defaultVnodeCount();
409
410 static native long iteratorNewStreamChunk(long pointer);
411
412 static native boolean iteratorNext(long pointer);
413
414 public static native void initObjectStoreForTest(String stateStoreUrl, String dataDirectory);
415
416 public static native void putObject(String objectName, byte[] data);
417
418 public static native String getObjectStoreType();
419
420 public static native void deleteObjects(String dir);
421
422 public static native byte[] getObject(String objectName);
423
424 public static native String[] listObject(String dir);
425
426 static native void iteratorClose(long pointer);
427
428 static native long newStreamChunkFromPayload(byte[] streamChunkPayload);
429
430 static native long newStreamChunkFromPretty(String str);
431
432 static native void streamChunkClose(long pointer);
433
434 static native byte[] iteratorGetKey(long pointer);
435
436 static native int iteratorGetOp(long pointer);
437
438 static native boolean iteratorIsNull(long pointer, int index);
439
440 static native short iteratorGetInt16Value(long pointer, int index);
441
442 static native int iteratorGetInt32Value(long pointer, int index);
443
444 static native long iteratorGetInt64Value(long pointer, int index);
445
446 static native float iteratorGetFloatValue(long pointer, int index);
447
448 static native double iteratorGetDoubleValue(long pointer, int index);
449
450 static native boolean iteratorGetBooleanValue(long pointer, int index);
451
452 static native String iteratorGetStringValue(long pointer, int index);
453
454 static native java.time.LocalDateTime iteratorGetTimestampValue(long pointer, int index);
455
456 static native java.time.OffsetDateTime iteratorGetTimestamptzValue(long pointer, int index);
457
458 static native java.math.BigDecimal iteratorGetDecimalValue(long pointer, int index);
459
460 static native java.time.LocalTime iteratorGetTimeValue(long pointer, int index);
461
462 static native java.time.LocalDate iteratorGetDateValue(long pointer, int index);
463
464 static native String iteratorGetIntervalValue(long pointer, int index);
465
466 static native String iteratorGetJsonbValue(long pointer, int index);
467
468 static native byte[] iteratorGetByteaValue(long pointer, int index);
469
470 static native Object iteratorGetArrayValue(long pointer, int index, Class<?> clazz);
472
473 public static native boolean sendCdcSourceMsgToChannel(long channelPtr, byte[] msg);
474
475 public static native boolean sendCdcSourceErrorToChannel(long channelPtr, String errorMsg);
476
477 public static native void cdcSourceSenderClose(long channelPtr);
478
479 public static native com.risingwave.java.binding.JniSinkWriterStreamRequest
480 recvSinkWriterRequestFromChannel(long channelPtr);
481
482 public static native boolean sendSinkWriterResponseToChannel(long channelPtr, byte[] msg);
483
484 public static native boolean sendSinkWriterErrorToChannel(long channelPtr, String msg);
485
486 public static native byte[] recvSinkCoordinatorRequestFromChannel(long channelPtr);
487
488 public static native boolean sendSinkCoordinatorResponseToChannel(long channelPtr, byte[] msg);
489 }
490 $(,$args)*
491 }
492 };
493}
494
495#[macro_export]
525macro_rules! split_extract_plain_native_methods {
526 (
527 {$($input:tt)*},
528 $macro:path
529 $(,$extra_args:tt)*
530 ) => {{
531 $crate::split_extract_plain_native_methods! {
532 {$($input)*},
533 {},
534 $macro
535 $(,$extra_args)*
536 }
537 }};
538 (
539 {
540 $(public)? static native $($first:tt)*
541 },
542 {
543 $($second:tt)*
544 },
545 $macro:path
546 $(,$extra_args:tt)*
547 ) => {
548 $crate::split_extract_plain_native_methods! {
549 {
550 $($first)*
551 },
552 {
553 $($second)*
554 },
555 $macro
556 $(,$extra_args)*
557 }
558 };
559 (
560 {
561 $($ret:tt).+ $func_name:ident($($args:tt)*); $($rest:tt)*
562 },
563 {
564 $({$prev_func_name:ident, {$($prev_ret:tt)*}, {$($prev_args:tt)*}})*
565 },
566 $macro:path
567 $(,$extra_args:tt)*
568 ) => {
569 $crate::split_extract_plain_native_methods! {
570 {$($rest)*},
571 {
572 $({$prev_func_name, {$($prev_ret)*}, {$($prev_args)*}})*
573 {$func_name, {$($ret).+}, {$($args)*}}
574 },
575 $macro
576 $(,$extra_args)*
577 }
578 };
579 (
580 {
581 $($ret:tt).+ [] $func_name:ident($($args:tt)*); $($rest:tt)*
582 },
583 {
584 $({$prev_func_name:ident, {$($prev_ret:tt)*}, {$($prev_args:tt)*}})*
585 },
586 $macro:path
587 $(,$extra_args:tt)*
588 ) => {
589 $crate::split_extract_plain_native_methods! {
590 {$($rest)*},
591 {
592 $({$prev_func_name, {$($prev_ret)*}, {$($prev_args)*}})*
593 {$func_name, {$($ret).+ []}, {$($args)*}}
594 },
595 $macro
596 $(,$extra_args)*
597 }
598 };
599 (
600 {},
601 {
602 $({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*
603 },
604 $macro:path
605 $(,$extra_args:tt)*
606 ) => {
607 $macro! {
608 {
609 $({$func_name, {$($ret)*}, {$($args)*}})*
610 }
611 $(,$extra_args)*
612 }
613 };
614 ($($invalid:tt)*) => {
615 compile_error!(concat!("unable to split extract `", stringify!($($invalid)*), "`"))
616 };
617}
618
619#[macro_export]
622macro_rules! for_all_native_methods {
623 ($macro:path $(,$args:tt)*) => {{
624 $crate::for_all_plain_native_methods! {
625 $crate::for_all_native_methods,
626 $macro
627 $(,$args)*
628 }
629 }};
630 (
631 {
632 $({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*
633 },
634 $macro:path
635 $(,$extra_args:tt)*
636 ) => {{
637 $macro! {
638 {$({$func_name, {$($ret)*}, {$($args)*}})*}
639 $(,$extra_args)*
640 }
641 }};
642 (
643 {$($input:tt)*},
644 $macro:path
645 $(,$extra_args:tt)*
646 ) => {{
647 $crate::split_extract_plain_native_methods! {
648 {$($input)*},
649 $crate::for_all_native_methods,
650 $macro
651 $(,$extra_args)*
652 }
653 }};
654}
655
656#[macro_export]
679macro_rules! convert_args_list {
680 (
681 {
682 {$($first_args:tt)+}
683 $({$($args:tt)+})*
684 },
685 {
686 {$first_value:expr}
687 $({$value:expr})*
688 },
689 {
690 $({$converted:expr})*
691 }) => {
692 $crate::convert_args_list! {
693 {$({$($args)+})*},
694 {$({$value})*},
695 {
696 $({$converted})*
697 {
698 $crate::to_jvalue! {
699 {$($first_args)+},
700 {$first_value}
701 }
702 }
703 }
704 }
705 };
706 ({$($args:tt)+}, {}, {$({$converted:expr})*}) => {
707 compile_error! {concat!{"trailing argument not passed: ", stringify!{$($args)+}}}
708 };
709 ({}, {$($value:tt)+}, {$({$converted:expr})*}) => {
710 compile_error! {concat!{"trailing extra value passed: ", stringify!{$($value)+}}}
711 };
712 ({}, {}, {$({$converted:expr})*}) => {
713 [$(
714 $converted
715 ),*]
716 };
717 ({$($args:tt)*}, {$($value:expr),*}) => {{
718 $crate::split_by_comma! {
719 {$($args)*},
720 $crate::convert_args_list,
721 {$({$value})*},
722 {}
723 }
724 }};
725 ($($invalid:tt)*) => {
726 compile_error!(concat!("failed to convert `", stringify!($($invalid)*), "`"))
727 };
728}
729
730#[macro_export]
731macro_rules! call_static_method {
732 (
733 {{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}},
734 {$($class:ident).+},
735 {$env:expr} $(, $method_args:expr)*
736 ) => {{
737 $crate::call_static_method! {
738 $env,
739 $crate::gen_class_name!($($class).+),
740 stringify! {$func_name},
741 {{$($ret)*}, {$($args)*}}
742 $(, $method_args)*
743 }
744 }};
745 ($env:expr, {$($class:ident).+}, {$($method:tt)*} $(, $args:expr)*) => {{
746 $crate::split_extract_plain_native_methods! {
747 {$($method)*;},
748 $crate::call_static_method,
749 {$($class).+},
750 {$env} $(, $args)*
751 }
752 }};
753 (
754 $env:expr,
755 $class_name:expr,
756 $func_name:expr,
757 {{$($ret:tt)*}, {$($args:tt)*}}
758 $(, $method_args:expr)*
759 ) => {{
760 $env.call_static_method(
761 $class_name,
762 $func_name,
763 $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}},
764 &{
765 $crate::convert_args_list! {
766 {$($args)*},
767 {$($method_args),*}
768 }
769 },
770 ).map(|jvalue| {
771 $crate::cast_jvalue! {
772 {$($ret)*},
773 jvalue
774 }
775 })
776 }};
777}
778
779#[macro_export]
780macro_rules! call_method {
781 (
782 {{$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}}},
783 $env:expr, $obj:expr $(, $method_args:expr)*
784 ) => {{
785 $env.call_method(
786 $obj,
787 stringify!{$func_name},
788 $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}},
789 &{
790 $crate::convert_args_list! {
791 {$($args)*},
792 {$($method_args),*}
793 }
794 },
795 ).map(|jvalue| {
796 $crate::cast_jvalue! {
797 {$($ret)*},
798 jvalue
799 }
800 })
801 }};
802 ($env:expr, $obj:expr, {$($method:tt)*} $(, $args:expr)*) => {{
803 $crate::split_extract_plain_native_methods! {
804 {$($method)*;},
805 $crate::call_method,
806 $env, $obj $(, $args)*
807 }
808 }};
809}
810
811#[macro_export]
812macro_rules! gen_native_method_entry {
813 (
814 $class_prefix:ident, $func_name:ident, {$($ret:tt)+}, {$($args:tt)*}
815 ) => {{
816 {
817 let fn_ptr = $crate::paste! {[<$class_prefix $func_name> ]} as *mut c_void;
818 let sig = $crate::gen_jni_sig! { {$($ret)+}, {$($args)*}};
819 jni::NativeMethod {
820 name: jni::strings::JNIString::from(stringify! {$func_name}),
821 sig: jni::strings::JNIString::from(sig),
822 fn_ptr,
823 }
824 }
825 }};
826}
827
828#[cfg(test)]
829mod tests {
830 use std::fmt::Formatter;
831
832 #[test]
833 fn test_for_all_gen() {
834 macro_rules! gen_array {
835 (test) => {{
836 for_all_native_methods! {
837 {
838 public static native int defaultVnodeCount();
839 static native long hummockIteratorNew(byte[] readPlan);
840 public static native byte[] rowGetKey(long pointer);
841 },
842 gen_array
843 }
844 }};
845 (all) => {{
846 for_all_native_methods! {
847 gen_array
848 }
849 }};
850 ({$({ $func_name:ident, {$($ret:tt)+}, {$($args:tt)*} })*}) => {{
851 [
852 $(
853 (stringify! {$func_name}, gen_jni_sig! { {$($ret)+}, {$($args)*}}),
854 )*
855 ]
856 }};
857 }
858 let sig: [(_, _); 3] = gen_array!(test);
859 assert_eq!(
860 sig,
861 [
862 ("defaultVnodeCount", "()I"),
863 ("hummockIteratorNew", "([B)J"),
864 ("rowGetKey", "(J)[B")
865 ]
866 );
867
868 let sig = gen_array!(all);
869 assert!(!sig.is_empty());
870 }
871
872 #[test]
873 fn test_all_native_methods() {
874 let expected = expect_test::expect![[r#"
876 [
877 tracingSlf4jEvent (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V,
878 tracingSlf4jEventEnabled (I)Z,
879 defaultVnodeCount ()I,
880 iteratorNewStreamChunk (J)J,
881 iteratorNext (J)Z,
882 initObjectStoreForTest (Ljava/lang/String;Ljava/lang/String;)V,
883 putObject (Ljava/lang/String;[B)V,
884 getObjectStoreType ()Ljava/lang/String;,
885 deleteObjects (Ljava/lang/String;)V,
886 getObject (Ljava/lang/String;)[B,
887 listObject (Ljava/lang/String;)[Ljava/lang/String;,
888 iteratorClose (J)V,
889 newStreamChunkFromPayload ([B)J,
890 newStreamChunkFromPretty (Ljava/lang/String;)J,
891 streamChunkClose (J)V,
892 iteratorGetKey (J)[B,
893 iteratorGetOp (J)I,
894 iteratorIsNull (JI)Z,
895 iteratorGetInt16Value (JI)S,
896 iteratorGetInt32Value (JI)I,
897 iteratorGetInt64Value (JI)J,
898 iteratorGetFloatValue (JI)F,
899 iteratorGetDoubleValue (JI)D,
900 iteratorGetBooleanValue (JI)Z,
901 iteratorGetStringValue (JI)Ljava/lang/String;,
902 iteratorGetTimestampValue (JI)Ljava/time/LocalDateTime;,
903 iteratorGetTimestamptzValue (JI)Ljava/time/OffsetDateTime;,
904 iteratorGetDecimalValue (JI)Ljava/math/BigDecimal;,
905 iteratorGetTimeValue (JI)Ljava/time/LocalTime;,
906 iteratorGetDateValue (JI)Ljava/time/LocalDate;,
907 iteratorGetIntervalValue (JI)Ljava/lang/String;,
908 iteratorGetJsonbValue (JI)Ljava/lang/String;,
909 iteratorGetByteaValue (JI)[B,
910 iteratorGetArrayValue (JILjava/lang/Class;)Ljava/lang/Object;,
911 sendCdcSourceMsgToChannel (J[B)Z,
912 sendCdcSourceErrorToChannel (JLjava/lang/String;)Z,
913 cdcSourceSenderClose (J)V,
914 recvSinkWriterRequestFromChannel (J)Lcom/risingwave/java/binding/JniSinkWriterStreamRequest;,
915 sendSinkWriterResponseToChannel (J[B)Z,
916 sendSinkWriterErrorToChannel (JLjava/lang/String;)Z,
917 recvSinkCoordinatorRequestFromChannel (J)[B,
918 sendSinkCoordinatorResponseToChannel (J[B)Z,
919 ]
920 "#]];
921
922 struct MethodInfo {
923 name: &'static str,
924 sig: &'static str,
925 }
926
927 impl std::fmt::Debug for MethodInfo {
928 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
929 write!(f, "{:40} {}", self.name, self.sig)
930 }
931 }
932
933 macro_rules! gen_all_native_method_info {
934 () => {{
935 $crate::for_all_native_methods! {
936 gen_all_native_method_info
937 }
938 }};
939 ({$({$func_name:ident, {$($ret:tt)*}, {$($args:tt)*}})*}) => {
940 [$(
941 (
942 MethodInfo {
943 name: stringify! {$func_name},
944 sig: $crate::gen_jni_sig! {
945 {$($ret)*}, {$($args)*}
946 },
947 }
948 )
949 ),*]
950 }
951 }
952 let info = gen_all_native_method_info!();
953 expected.assert_debug_eq(&info);
954 }
955}